1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  */
20 
21 #include "config.h"
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <signal.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 
33 #ifdef HAVE_PATHS_H
34 #include <paths.h>
35 #endif /* HAVE_PATHS_H */
36 
37 #include <glib.h>
38 #include <glib/gi18n-lib.h>
39 #include <glib/gstdio.h>
40 #include <glib-object.h>
41 #include <gio/gio.h>
42 #include <gio/gunixinputstream.h>
43 
44 #ifdef WITH_SYSTEMD
45 #include <systemd/sd-login.h>
46 
47 /* check if logind is running */
48 #define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0)
49 #endif
50 
51 #include "act-user-manager.h"
52 #include "act-user-private.h"
53 #include "accounts-generated.h"
54 #include "ck-manager-generated.h"
55 #include "ck-seat-generated.h"
56 #include "ck-session-generated.h"
57 
58 /**
59  * SECTION:act-user-manager
60  * @title: ActUserManager
61  * @short_description: manages ActUser objects
62  *
63  * ActUserManager is a manager object that gives access to user
64  * creation, deletion, enumeration, etc.
65  *
66  * There is typically a singleton ActUserManager object, which
67  * can be obtained by act_user_manager_get_default().
68  */
69 
70 /**
71  * ActUserManager:
72  *
73  * A user manager object.
74  */
75 
76 /**
77  * ACT_USER_MANAGER_ERROR:
78  *
79  * The GError domain for #ActUserManagerError errors
80  */
81 
82 /**
83  * ActUserManagerError:
84  * @ACT_USER_MANAGER_ERROR_FAILED: Generic failure
85  * @ACT_USER_MANAGER_ERROR_USER_EXISTS: The user already exists
86  * @ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST: The user does not exist
87  * @ACT_USER_MANAGER_ERROR_PERMISSION_DENIED: Permission denied
88  * @ACT_USER_MANAGER_ERROR_NOT_SUPPORTED: Operation not supported
89  *
90  * Various error codes returned by the accounts service.
91  */
92 
93 #define CK_NAME      "org.freedesktop.ConsoleKit"
94 
95 #define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
96 #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
97 #define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
98 #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
99 
100 #define ACCOUNTS_NAME      "org.freedesktop.Accounts"
101 #define ACCOUNTS_PATH      "/org/freedesktop/Accounts"
102 #define ACCOUNTS_INTERFACE "org.freedesktop.Accounts"
103 
104 typedef enum {
105         ACT_USER_MANAGER_SEAT_STATE_UNLOADED = 0,
106         ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_ID,
107         ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_PROXY,
108         ACT_USER_MANAGER_SEAT_STATE_GET_ID,
109         ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY,
110         ACT_USER_MANAGER_SEAT_STATE_LOADED,
111 } ActUserManagerSeatState;
112 
113 typedef struct
114 {
115         ActUserManagerSeatState      state;
116         char                        *id;
117         char                        *session_id;
118         ConsoleKitSeat              *seat_proxy;
119         ConsoleKitSession           *session_proxy;
120         guint                        load_idle_id;
121 #ifdef WITH_SYSTEMD
122         sd_login_monitor            *session_monitor;
123         GInputStream                *session_monitor_stream;
124         guint                        session_monitor_source_id;
125 #endif
126 } ActUserManagerSeat;
127 
128 typedef enum {
129         ACT_USER_MANAGER_NEW_SESSION_STATE_UNLOADED = 0,
130         ACT_USER_MANAGER_NEW_SESSION_STATE_GET_PROXY,
131         ACT_USER_MANAGER_NEW_SESSION_STATE_GET_UID,
132         ACT_USER_MANAGER_NEW_SESSION_STATE_GET_X11_DISPLAY,
133         ACT_USER_MANAGER_NEW_SESSION_STATE_MAYBE_ADD,
134         ACT_USER_MANAGER_NEW_SESSION_STATE_LOADED,
135 } ActUserManagerNewSessionState;
136 
137 typedef struct
138 {
139         ActUserManager                  *manager;
140         ActUserManagerNewSessionState    state;
141         char                            *id;
142         ConsoleKitSession               *proxy;
143         GCancellable                    *cancellable;
144         uid_t                            uid;
145         char                            *x11_display;
146         gsize                            pending_calls;
147 } ActUserManagerNewSession;
148 
149 typedef enum {
150         ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED = 0,
151         ACT_USER_MANAGER_GET_USER_STATE_WAIT_FOR_LOADED,
152         ACT_USER_MANAGER_GET_USER_STATE_ASK_ACCOUNTS_SERVICE,
153         ACT_USER_MANAGER_GET_USER_STATE_FETCHED
154 } ActUserManagerGetUserState;
155 
156 typedef enum {
157         ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST,
158         ACT_USER_MANAGER_FETCH_USER_FROM_ID_REQUEST,
159 } ActUserManagerFetchUserRequestType;
160 
161 typedef struct
162 {
163         ActUserManager             *manager;
164         ActUserManagerGetUserState  state;
165         ActUser                    *user;
166         ActUserManagerFetchUserRequestType type;
167         union {
168                 char               *username;
169                 uid_t               uid;
170         };
171         char                       *object_path;
172         char                       *description;
173 } ActUserManagerFetchUserRequest;
174 
175 typedef struct
176 {
177         GHashTable            *normal_users_by_name;
178         GHashTable            *system_users_by_name;
179         GHashTable            *users_by_object_path;
180         GHashTable            *sessions;
181         GDBusConnection       *connection;
182         AccountsAccounts      *accounts_proxy;
183         ConsoleKitManager     *ck_manager_proxy;
184 
185         ActUserManagerSeat     seat;
186 
187         GSList                *new_sessions;
188         GSList                *new_users;
189         GSList                *new_users_inhibiting_load;
190         GSList                *fetch_user_requests;
191 
192         GSList                *exclude_usernames;
193         GSList                *include_usernames;
194 
195         guint                  load_id;
196 
197         gboolean               is_loaded;
198         gboolean               has_multiple_users;
199         gboolean               getting_sessions;
200         gboolean               list_cached_users_done;
201 } ActUserManagerPrivate;
202 
203 enum {
204         PROP_0,
205         PROP_INCLUDE_USERNAMES_LIST,
206         PROP_EXCLUDE_USERNAMES_LIST,
207         PROP_IS_LOADED,
208         PROP_HAS_MULTIPLE_USERS
209 };
210 
211 enum {
212         USER_ADDED,
213         USER_REMOVED,
214         USER_IS_LOGGED_IN_CHANGED,
215         USER_CHANGED,
216         LAST_SIGNAL
217 };
218 
219 static guint signals [LAST_SIGNAL] = { 0, };
220 
221 static void     act_user_manager_class_init (ActUserManagerClass *klass);
222 static void     act_user_manager_init       (ActUserManager      *user_manager);
223 static void     act_user_manager_finalize   (GObject             *object);
224 
225 static gboolean ensure_accounts_proxy       (ActUserManager *manager);
226 static gboolean load_seat_incrementally     (ActUserManager *manager);
227 static void     unload_seat                 (ActUserManager *manager);
228 static void     load_users                  (ActUserManager *manager);
229 static void     load_user                   (ActUserManager *manager,
230                                              const char     *username);
231 static void     act_user_manager_queue_load (ActUserManager *manager);
232 static void     queue_load_seat             (ActUserManager *manager);
233 
234 static void     load_new_session_incrementally (ActUserManagerNewSession *new_session);
235 static void     set_is_loaded (ActUserManager *manager, gboolean is_loaded);
236 
237 static void     on_new_user_loaded (ActUser        *user,
238                                     GParamSpec     *pspec,
239                                     ActUserManager *manager);
240 static void     give_up (ActUserManager                 *manager,
241                          ActUserManagerFetchUserRequest *request);
242 static void     fetch_user_incrementally       (ActUserManagerFetchUserRequest *request);
243 
244 static void     maybe_set_is_loaded            (ActUserManager *manager);
245 static void     update_user                    (ActUserManager *manager,
246                                                 ActUser        *user);
247 static gpointer user_manager_object = NULL;
248 
249 G_DEFINE_TYPE_WITH_PRIVATE (ActUserManager, act_user_manager, G_TYPE_OBJECT)
250 
251 static const GDBusErrorEntry error_entries[] = {
252         { ACT_USER_MANAGER_ERROR_FAILED,              "org.freedesktop.Accounts.Error.Failed" },
253         { ACT_USER_MANAGER_ERROR_USER_EXISTS,         "org.freedesktop.Accounts.Error.UserExists" },
254         { ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
255         { ACT_USER_MANAGER_ERROR_PERMISSION_DENIED,   "org.freedesktop.Accounts.Error.PermissionDenied" },
256         { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED,       "org.freedesktop.Accounts.Error.NotSupported" }
257 };
258 
259 GQuark
act_user_manager_error_quark(void)260 act_user_manager_error_quark (void)
261 {
262         static volatile gsize ret = 0;
263         if (ret == 0) {
264                 g_dbus_error_register_error_domain ("act_user_manager_error",
265                                                     &ret,
266                                                     error_entries,
267                                                     G_N_ELEMENTS (error_entries));
268         }
269 
270         return (GQuark) ret;
271 }
272 
273 static gboolean
activate_console_kit_session_id(ActUserManager * manager,const char * seat_id,const char * session_id)274 activate_console_kit_session_id (ActUserManager *manager,
275                                  const char     *seat_id,
276                                  const char     *session_id)
277 {
278         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
279         ConsoleKitSeat *proxy;
280         g_autoptr(GError) error = NULL;
281         gboolean res = FALSE;
282 
283         proxy = console_kit_seat_proxy_new_sync (priv->connection,
284                                                  G_DBUS_PROXY_FLAGS_NONE,
285                                                  CK_NAME,
286                                                  seat_id,
287                                                  NULL,
288                                                  &error);
289         if (proxy)
290                 res = console_kit_seat_call_activate_session_sync (proxy,
291                                                                    session_id,
292                                                                    NULL,
293                                                                    &error);
294 
295         if (!res) {
296                 g_warning ("Unable to activate session: %s", error->message);
297                 return FALSE;
298         }
299 
300         return TRUE;
301 }
302 
303 #ifdef WITH_SYSTEMD
304 static gboolean
activate_systemd_session_id(ActUserManager * manager,const char * seat_id,const char * session_id)305 activate_systemd_session_id (ActUserManager *manager,
306                              const char     *seat_id,
307                              const char     *session_id)
308 {
309         g_autoptr(GDBusConnection) connection = NULL;
310         g_autoptr(GVariant) reply = NULL;
311         g_autoptr(GError) error = NULL;
312 
313         connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
314         if (connection == NULL) {
315                 g_warning ("Unable to activate session: %s", error->message);
316                 return FALSE;
317         }
318 
319         reply = g_dbus_connection_call_sync (connection,
320                                              "org.freedesktop.login1",
321                                              "/org/freedesktop/login1",
322                                              "org.freedesktop.login1.Manager",
323                                              "ActivateSessionOnSeat",
324                                              g_variant_new ("(ss)",
325                                                             seat_id,
326                                                             session_id),
327                                              NULL,
328                                              G_DBUS_CALL_FLAGS_NONE,
329                                              -1,
330                                              NULL,
331                                              &error);
332         if (reply == NULL) {
333                 g_warning ("Unable to activate session: %s", error->message);
334                 return FALSE;
335         }
336 
337         return TRUE;
338 }
339 #endif
340 
341 static gboolean
_ck_session_is_login_window(ActUserManager * manager,const char * session_id)342 _ck_session_is_login_window (ActUserManager *manager,
343                              const char     *session_id)
344 {
345         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
346         ConsoleKitSession *proxy;
347         g_autoptr(GError) error = NULL;
348         g_autofree gchar *session_type = NULL;
349         gboolean res = FALSE;
350 
351         proxy = console_kit_session_proxy_new_sync (priv->connection,
352                                                     G_DBUS_PROXY_FLAGS_NONE,
353                                                     CK_NAME,
354                                                     session_id,
355                                                     NULL,
356                                                     &error);
357         if (proxy)
358                 res = console_kit_session_call_get_session_type_sync (proxy, &session_type, NULL, &error);
359 
360         if (!res) {
361                 if (error != NULL) {
362                         g_debug ("ActUserManager: Failed to identify the session type: %s", error->message);
363                 } else {
364                         g_debug ("ActUserManager: Failed to identify the session type");
365                 }
366                 return FALSE;
367         }
368         if (proxy)
369                 g_object_unref (proxy);
370 
371         return strcmp (session_type, "LoginWindow") == 0;
372 }
373 
374 #ifdef WITH_SYSTEMD
375 static gboolean
_systemd_session_is_login_window(ActUserManager * manager,const char * session_id)376 _systemd_session_is_login_window (ActUserManager *manager,
377                                   const char     *session_id)
378 {
379         int   res;
380         g_autofree gchar *session_class = NULL;
381 
382         res = sd_session_get_class (session_id, &session_class);
383         if (res < 0) {
384             g_debug ("failed to determine class of session %s: %s",
385                      session_id,
386                      strerror (-res));
387             return FALSE;
388         }
389 
390         return g_strcmp0 (session_class, "greeter") == 0;
391 }
392 #endif
393 
394 static gboolean
session_is_login_window(ActUserManager * manager,const char * session_id)395 session_is_login_window (ActUserManager *manager,
396                          const char     *session_id)
397 {
398 #ifdef WITH_SYSTEMD
399         if (LOGIND_RUNNING()) {
400                 return _systemd_session_is_login_window (manager, session_id);
401         }
402 #endif
403 
404         return _ck_session_is_login_window (manager, session_id);
405 }
406 
407 static gboolean
_ck_session_is_on_our_seat(ActUserManager * manager,const char * session_id)408 _ck_session_is_on_our_seat (ActUserManager *manager,
409                             const char     *session_id)
410 {
411         /* With ConsoleKit, we only ever see sessions on our seat. */
412         return TRUE;
413 }
414 
415 #ifdef WITH_SYSTEMD
416 static gboolean
_systemd_session_is_on_our_seat(ActUserManager * manager,const char * session_id)417 _systemd_session_is_on_our_seat (ActUserManager *manager,
418                                  const char     *session_id)
419 {
420         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
421         int   res;
422         g_autofree gchar *session_seat = NULL;
423 
424         res = sd_session_get_seat (session_id, &session_seat);
425         if (res == -ENODATA) {
426                 return FALSE;
427         } else if (res < 0) {
428                 g_debug ("failed to determine seat of session %s: %s",
429                          session_id,
430                          strerror (-res));
431                 return FALSE;
432         }
433 
434         return g_strcmp0 (priv->seat.id, session_seat) == 0;
435 }
436 #endif
437 
438 static gboolean
session_is_on_our_seat(ActUserManager * manager,const char * session_id)439 session_is_on_our_seat (ActUserManager *manager,
440                         const char     *session_id)
441 {
442 #ifdef WITH_SYSTEMD
443         if (LOGIND_RUNNING()) {
444                 return _systemd_session_is_on_our_seat (manager, session_id);
445         }
446 #endif
447 
448         return _ck_session_is_on_our_seat (manager, session_id);
449 }
450 
451 /**
452  * act_user_manager_goto_login_session:
453  * @manager: the user manager
454  *
455  * Switch the display to the login manager.
456  *
457  * Returns: whether successful or not
458  */
459 gboolean
act_user_manager_goto_login_session(ActUserManager * manager)460 act_user_manager_goto_login_session (ActUserManager *manager)
461 {
462         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
463         gboolean res;
464         g_autoptr(GError) error = NULL;
465 
466         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), FALSE);
467         g_return_val_if_fail (priv->is_loaded, FALSE);
468 
469         res = g_spawn_command_line_async ("gdmflexiserver", &error);
470         if (!res) {
471                 if (error != NULL) {
472                         g_warning ("Unable to start new login: %s", error->message);
473                 } else {
474                         g_warning ("Unable to start new login");
475                 }
476         }
477 
478         return res;
479 
480 }
481 
482 #ifdef WITH_SYSTEMD
483 static gboolean
_can_activate_systemd_sessions(ActUserManager * manager)484 _can_activate_systemd_sessions (ActUserManager *manager)
485 {
486         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
487         int res;
488 
489         res = sd_seat_can_multi_session (priv->seat.id);
490         if (res < 0) {
491                 g_warning ("unable to determine if seat %s can activate sessions: %s",
492                            priv->seat.id, strerror (-res));
493                 return FALSE;
494         }
495 
496         return res > 0;
497 }
498 #endif
499 
500 gboolean
_can_activate_console_kit_sessions(ActUserManager * manager)501 _can_activate_console_kit_sessions (ActUserManager *manager)
502 {
503         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
504         g_autoptr(GError) error = NULL;
505         gboolean  can_activate_sessions = FALSE;
506 
507         if (!console_kit_seat_call_can_activate_sessions_sync (priv->seat.seat_proxy, &can_activate_sessions, NULL, &error)) {
508                 if (error != NULL) {
509                         g_warning ("unable to determine if seat can activate sessions: %s",
510                                    error->message);
511                 } else {
512                         g_warning ("unable to determine if seat can activate sessions");
513                 }
514                 return FALSE;
515         }
516 
517         return can_activate_sessions;
518 }
519 
520 /**
521  * act_user_manager_can_switch:
522  * @manager: the user manager
523  *
524  * Check whether the user can switch to another session.
525  *
526  * Returns: whether we can switch to another session
527  */
528 gboolean
act_user_manager_can_switch(ActUserManager * manager)529 act_user_manager_can_switch (ActUserManager *manager)
530 {
531         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
532 
533         if (!priv->is_loaded) {
534                 g_debug ("ActUserManager: Unable to switch sessions until fully loaded");
535                 return FALSE;
536         }
537 
538         if (priv->seat.id == NULL || priv->seat.id[0] == '\0') {
539                 g_debug ("ActUserManager: display seat ID is not set; can't switch sessions");
540                 return FALSE;
541         }
542 
543         g_debug ("ActUserManager: checking if seat can activate sessions");
544 
545 
546 #ifdef WITH_SYSTEMD
547         if (LOGIND_RUNNING()) {
548                 return _can_activate_systemd_sessions (manager);
549         }
550 #endif
551 
552         return _can_activate_console_kit_sessions (manager);
553 }
554 
555 /**
556  * act_user_manager_activate_user_session:
557  * @manager: the user manager
558  * @user: the user to activate
559  *
560  * Activate the session for a given user.
561  *
562  * Returns: whether successfully activated
563  */
564 gboolean
act_user_manager_activate_user_session(ActUserManager * manager,ActUser * user)565 act_user_manager_activate_user_session (ActUserManager *manager,
566                                         ActUser        *user)
567 {
568         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
569         gboolean can_activate_sessions;
570         const char *ssid;
571 
572         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), FALSE);
573         g_return_val_if_fail (ACT_IS_USER (user), FALSE);
574         g_return_val_if_fail (priv->is_loaded, FALSE);
575 
576         can_activate_sessions = act_user_manager_can_switch (manager);
577 
578         if (!can_activate_sessions) {
579                 g_debug ("ActUserManager: seat is unable to activate sessions");
580                 return FALSE;
581         }
582 
583         ssid = act_user_get_primary_session_id (user);
584         if (ssid == NULL) {
585                 return FALSE;
586         }
587 
588 #ifdef WITH_SYSTEMD
589         if (LOGIND_RUNNING()) {
590                 return activate_systemd_session_id (manager, priv->seat.id, ssid);
591         }
592 #endif
593 
594         if (!activate_console_kit_session_id (manager, priv->seat.id, ssid)) {
595                 g_debug ("ActUserManager: unable to activate session: %s", ssid);
596                 return FALSE;
597         }
598 
599         return TRUE;
600 }
601 
602 static const char *
describe_user(ActUser * user)603 describe_user (ActUser *user)
604 {
605         ActUserManagerFetchUserRequest *request;
606 
607         if (act_user_is_loaded (user)) {
608                 static char *description = NULL;
609                 g_clear_pointer (&description, (GDestroyNotify) g_free);
610 
611                 description = g_strdup_printf ("user %s", act_user_get_user_name (user));
612                 return description;
613         }
614 
615         request = g_object_get_data (G_OBJECT (user), "fetch-user-request");
616 
617         if (request != NULL) {
618                 return request->description;
619         }
620 
621         return "user";
622 }
623 
624 static void
on_user_sessions_changed(ActUser * user,ActUserManager * manager)625 on_user_sessions_changed (ActUser        *user,
626                           ActUserManager *manager)
627 {
628         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
629         guint nsessions;
630 
631         if (!priv->is_loaded) {
632                 return;
633         }
634 
635         nsessions = act_user_get_num_sessions (user);
636 
637         g_debug ("ActUserManager: sessions changed (%s) num=%d",
638                  describe_user (user),
639                  nsessions);
640 
641         /* only signal on zero and one */
642         if (nsessions > 1) {
643                 return;
644         }
645 
646         g_signal_emit (manager, signals [USER_IS_LOGGED_IN_CHANGED], 0, user);
647 }
648 
649 static void
on_user_changed(ActUser * user,ActUserManager * manager)650 on_user_changed (ActUser        *user,
651                  ActUserManager *manager)
652 {
653         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
654 
655         if (priv->is_loaded) {
656                 g_debug ("ActUserManager: sending user-changed signal for %s",
657                          describe_user (user));
658 
659                 g_signal_emit (manager, signals[USER_CHANGED], 0, user);
660 
661                 g_debug ("ActUserManager: sent user-changed signal for %s",
662                          describe_user (user));
663 
664                 update_user (manager, user);
665         }
666 }
667 
668 static void
queue_load_seat_incrementally(ActUserManager * manager)669 queue_load_seat_incrementally (ActUserManager *manager)
670 {
671         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
672 
673         if (priv->seat.load_idle_id == 0) {
674             priv->seat.load_idle_id = g_idle_add ((GSourceFunc) load_seat_incrementally, manager);
675         }
676 }
677 
678 static void
on_get_seat_id_finished(GObject * object,GAsyncResult * result,gpointer data)679 on_get_seat_id_finished (GObject        *object,
680                          GAsyncResult   *result,
681                          gpointer        data)
682 {
683         ConsoleKitSession *proxy = CONSOLE_KIT_SESSION (object);
684         g_autoptr(ActUserManager) manager = data;
685         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
686         g_autoptr(GError)  error = NULL;
687         char              *seat_id;
688 
689         if (!console_kit_session_call_get_seat_id_finish (proxy, &seat_id, result, &error)) {
690                 if (error != NULL) {
691                         g_debug ("Failed to identify the seat of the "
692                                  "current session: %s",
693                                  error->message);
694                 } else {
695                         g_debug ("Failed to identify the seat of the "
696                                  "current session");
697                 }
698 
699                 g_debug ("ActUserManager: GetSeatId call failed, so unloading seat");
700                 unload_seat (manager);
701 
702                 return;
703         }
704 
705         g_debug ("ActUserManager: Found current seat: %s", seat_id);
706 
707         priv->seat.id = seat_id;
708         priv->seat.state++;
709 }
710 
711 #ifdef WITH_SYSTEMD
712 static gboolean
_systemd_session_is_graphical(const char * session_id)713 _systemd_session_is_graphical (const char *session_id)
714 {
715         const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL };
716         int saved_errno;
717         g_autofree gchar *type = NULL;
718 
719         saved_errno = sd_session_get_type (session_id, &type);
720         if (saved_errno < 0) {
721                 g_warning ("Couldn't get type for session '%s': %s",
722                            session_id,
723                            g_strerror (-saved_errno));
724                 return FALSE;
725         }
726 
727         if (!g_strv_contains (graphical_session_types, type)) {
728                 g_debug ("Session '%s' is not a graphical session (type: '%s')",
729                          session_id,
730                          type);
731                 return FALSE;
732         }
733 
734         return TRUE;
735 }
736 
737 static gboolean
_systemd_session_is_active(const char * session_id)738 _systemd_session_is_active (const char *session_id)
739 {
740         const gchar * const active_states[] = { "active", "online", NULL };
741         int saved_errno;
742         g_autofree gchar *state = NULL;
743 
744         /*
745          * display sessions can be 'closing' if they are logged out but some
746          * processes are lingering; we shouldn't consider these (this is
747          * checking for a race condition since we specified that we want online
748          * sessions only)
749          */
750         saved_errno = sd_session_get_state (session_id, &state);
751         if (saved_errno < 0) {
752                 g_warning ("Couldn't get state for session '%s': %s",
753                            session_id,
754                            g_strerror (-saved_errno));
755                 return FALSE;
756         }
757 
758         if (!g_strv_contains (active_states, state)) {
759                 g_debug ("Session '%s' is not active or online", session_id);
760                 return FALSE;
761         }
762 
763         return TRUE;
764 }
765 
766 static gboolean
_find_graphical_systemd_session(char ** session_id)767 _find_graphical_systemd_session (char **session_id)
768 {
769         char *local_session_id = NULL;
770         g_auto(GStrv) sessions = NULL;
771         int n_sessions;
772 
773         /* filter level 0 means to include inactive and active sessions
774          * (>0 would mean to return only the active session, and <0 would mean to
775          * include closing sessions too)
776          */
777         static int filter_level = 0;
778 
779         g_return_val_if_fail (session_id != NULL, FALSE);
780 
781         g_debug ("Finding a graphical session for user %d", getuid ());
782 
783         n_sessions = sd_uid_get_sessions (getuid (), filter_level, &sessions);
784 
785         if (n_sessions < 0) {
786                 g_critical ("Failed to get sessions for user %d", getuid ());
787                 return FALSE;
788         }
789 
790         for (int i = 0; i < n_sessions; ++i) {
791                 g_debug ("Considering session '%s'", sessions[i]);
792 
793                 if (!_systemd_session_is_graphical (sessions[i]))
794                         continue;
795 
796                 if (!_systemd_session_is_active (sessions[i]))
797                         continue;
798 
799                 /*
800                  * We get the sessions from newest to oldest, so take the last
801                  * one we find that's good
802                  */
803                 local_session_id = sessions[i];
804         }
805 
806         if (local_session_id == NULL)
807                 return FALSE;
808 
809         *session_id = g_strdup (local_session_id);
810 
811         return TRUE;
812 }
813 
814 static void
_get_systemd_seat_id(ActUserManager * manager)815 _get_systemd_seat_id (ActUserManager *manager)
816 {
817         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
818         int   res;
819         g_autofree gchar *seat_id = NULL;
820 
821         if (priv->seat.session_id == NULL) {
822                 if (!_find_graphical_systemd_session (&priv->seat.session_id)) {
823                         g_warning ("Could not get session");
824                         return;
825                 }
826         }
827 
828         res = sd_session_get_seat (priv->seat.session_id, &seat_id);
829 
830         if (res == -ENODATA) {
831                 seat_id = NULL;
832         } else if (res < 0) {
833                 g_warning ("Could not get current seat: %s",
834                            strerror (-res));
835                 unload_seat (manager);
836                 return;
837         }
838 
839         priv->seat.id = g_strdup (seat_id);
840         priv->seat.state++;
841 }
842 #endif
843 
844 static void
get_seat_id_for_current_session(ActUserManager * manager)845 get_seat_id_for_current_session (ActUserManager *manager)
846 {
847         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
848 
849 #ifdef WITH_SYSTEMD
850         if (LOGIND_RUNNING()) {
851                 _get_systemd_seat_id (manager);
852                 return;
853         }
854 #endif
855         console_kit_session_call_get_seat_id (priv->seat.session_proxy,
856                                               NULL,
857                                               on_get_seat_id_finished,
858                                               g_object_ref (manager));
859 }
860 
861 static gint
match_name_cmpfunc(gconstpointer a,gconstpointer b)862 match_name_cmpfunc (gconstpointer a,
863                     gconstpointer b)
864 {
865         return g_strcmp0 ((char *) a,
866                           (char *) b);
867 }
868 
869 static gboolean
username_in_exclude_list(ActUserManager * manager,const char * username)870 username_in_exclude_list (ActUserManager *manager,
871                           const char     *username)
872 {
873         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
874         GSList   *found;
875         gboolean  ret = FALSE;
876 
877         if (priv->exclude_usernames != NULL) {
878                 found = g_slist_find_custom (priv->exclude_usernames,
879                                              username,
880                                              match_name_cmpfunc);
881                 if (found != NULL) {
882                         ret = TRUE;
883                 }
884         }
885 
886         return ret;
887 }
888 
889 static void
add_session_for_user(ActUserManager * manager,ActUser * user,const char * ssid,gboolean is_ours)890 add_session_for_user (ActUserManager *manager,
891                       ActUser        *user,
892                       const char     *ssid,
893                       gboolean        is_ours)
894 {
895         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
896 
897         g_hash_table_insert (priv->sessions,
898                              g_strdup (ssid),
899                              g_object_ref (user));
900 
901         _act_user_add_session (user, ssid, is_ours);
902         g_debug ("ActUserManager: added session for %s", describe_user (user));
903 }
904 
905 static void
set_has_multiple_users(ActUserManager * manager,gboolean has_multiple_users)906 set_has_multiple_users (ActUserManager *manager,
907                         gboolean        has_multiple_users)
908 {
909         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
910 
911         if (priv->has_multiple_users != has_multiple_users) {
912                 priv->has_multiple_users = has_multiple_users;
913                 g_object_notify (G_OBJECT (manager), "has-multiple-users");
914         }
915 }
916 
917 static ActUser *
create_new_user(ActUserManager * manager)918 create_new_user (ActUserManager *manager)
919 {
920         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
921         ActUser *user;
922 
923         user = g_object_new (ACT_TYPE_USER, NULL);
924 
925         priv->new_users = g_slist_prepend (priv->new_users, g_object_ref (user));
926 
927         g_signal_connect_object (user, "notify::is-loaded", G_CALLBACK (on_new_user_loaded), manager, 0);
928 
929         return user;
930 }
931 
932 static void
add_user(ActUserManager * manager,ActUser * user)933 add_user (ActUserManager *manager,
934           ActUser        *user)
935 {
936         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
937         const char *object_path;
938 
939         g_debug ("ActUserManager: tracking user '%s'", act_user_get_user_name (user));
940         if (act_user_is_system_account (user)) {
941                 g_hash_table_insert (priv->system_users_by_name,
942                                      g_strdup (act_user_get_user_name (user)),
943                                      g_object_ref (user));
944         } else {
945                 g_hash_table_insert (priv->normal_users_by_name,
946                                      g_strdup (act_user_get_user_name (user)),
947                                      g_object_ref (user));
948         }
949 
950         object_path = act_user_get_object_path (user);
951         if (object_path != NULL) {
952                 g_hash_table_replace (priv->users_by_object_path,
953                                       (gpointer) object_path,
954                                       g_object_ref (user));
955         }
956 
957         g_signal_connect_object (user,
958                                  "sessions-changed",
959                                  G_CALLBACK (on_user_sessions_changed),
960                                  manager, 0);
961         g_signal_connect_object (user,
962                                  "changed",
963                                  G_CALLBACK (on_user_changed),
964                                  manager, 0);
965 
966         if (priv->is_loaded && priv->list_cached_users_done) {
967                 g_debug ("ActUserManager: loaded, so emitting user-added signal");
968                 g_signal_emit (manager, signals[USER_ADDED], 0, user);
969         } else {
970                 g_debug ("ActUserManager: not yet loaded, so not emitting user-added signal");
971         }
972 }
973 
974 static void
remove_user(ActUserManager * manager,ActUser * user)975 remove_user (ActUserManager *manager,
976              ActUser        *user)
977 {
978         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
979 
980         g_debug ("ActUserManager: no longer tracking user '%s' (with object path %s)",
981                  act_user_get_user_name (user),
982                  act_user_get_object_path (user));
983 
984         g_object_ref (user);
985 
986         g_signal_handlers_disconnect_by_func (user, on_user_changed, manager);
987         g_signal_handlers_disconnect_by_func (user, on_user_sessions_changed, manager);
988         if (act_user_get_object_path (user) != NULL) {
989                 g_hash_table_remove (priv->users_by_object_path, act_user_get_object_path (user));
990         }
991         if (act_user_get_user_name (user) != NULL) {
992                 g_hash_table_remove (priv->normal_users_by_name, act_user_get_user_name (user));
993                 g_hash_table_remove (priv->system_users_by_name, act_user_get_user_name (user));
994 
995         }
996 
997         if (priv->is_loaded && priv->list_cached_users_done) {
998                 g_debug ("ActUserManager: loaded, so emitting user-removed signal");
999                 g_signal_emit (manager, signals[USER_REMOVED], 0, user);
1000         } else {
1001                 g_debug ("ActUserManager: not yet loaded, so not emitting user-removed signal");
1002         }
1003 
1004         g_debug ("ActUserManager: user '%s' (with object path %s) now removed",
1005                  act_user_get_user_name (user),
1006                  act_user_get_object_path (user));
1007         g_object_unref (user);
1008 }
1009 
1010 static void
update_user(ActUserManager * manager,ActUser * user)1011 update_user (ActUserManager *manager,
1012              ActUser        *user)
1013 {
1014         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1015         const char *username;
1016 
1017         g_debug ("ActUserManager: updating %s", describe_user (user));
1018 
1019         username = act_user_get_user_name (user);
1020         if (g_hash_table_lookup (priv->system_users_by_name, username) != NULL) {
1021                 if (!act_user_is_system_account (user)) {
1022                         g_debug ("ActUserManager: %s is no longer a system account, treating as normal user",
1023                                  describe_user (user));
1024                         g_hash_table_insert (priv->normal_users_by_name,
1025                                              g_strdup (act_user_get_user_name (user)),
1026                                              g_object_ref (user));
1027                         g_hash_table_remove (priv->system_users_by_name, username);
1028                         g_signal_emit (manager, signals[USER_ADDED], 0, user);
1029                 }
1030         } else {
1031                 if (act_user_is_system_account (user)) {
1032                         g_debug ("ActUserManager: %s is no longer a normal account, treating as system user",
1033                                  describe_user (user));
1034                         g_hash_table_insert (priv->system_users_by_name,
1035                                              g_strdup (act_user_get_user_name (user)),
1036                                              g_object_ref (user));
1037                         g_hash_table_remove (priv->normal_users_by_name, username);
1038                         g_signal_emit (manager, signals[USER_REMOVED], 0, user);
1039                 }
1040         }
1041 }
1042 
1043 static ActUser *
lookup_user_by_name(ActUserManager * manager,const char * username)1044 lookup_user_by_name (ActUserManager *manager,
1045                      const char     *username)
1046 {
1047         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1048         ActUser *user;
1049 
1050         user = g_hash_table_lookup (priv->normal_users_by_name, username);
1051 
1052         if (user == NULL) {
1053                 user = g_hash_table_lookup (priv->system_users_by_name, username);
1054         }
1055 
1056         return user;
1057 }
1058 
1059 static void
on_new_user_loaded(ActUser * user,GParamSpec * pspec,ActUserManager * manager)1060 on_new_user_loaded (ActUser        *user,
1061                     GParamSpec     *pspec,
1062                     ActUserManager *manager)
1063 {
1064         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1065         const char *username;
1066         ActUser *old_user;
1067 
1068         if (!act_user_is_loaded (user)) {
1069                 g_debug ("ActUserManager: %s loaded function called when not loaded",
1070                          describe_user (user));
1071                 return;
1072         }
1073         g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
1074 
1075         priv->new_users = g_slist_remove (priv->new_users,
1076                                           user);
1077         priv->new_users_inhibiting_load = g_slist_remove (priv->new_users_inhibiting_load,
1078                                                           user);
1079 
1080         username = act_user_get_user_name (user);
1081 
1082         if (username == NULL) {
1083                 const char *object_path;
1084 
1085                 object_path = act_user_get_object_path (user);
1086 
1087                 if (object_path != NULL) {
1088                         g_warning ("ActUserManager: %s has no username "
1089                                    "(object path: %s, uid: %d)",
1090                                    describe_user (user),
1091                                    object_path, (int) act_user_get_uid (user));
1092                 } else {
1093                         g_warning ("ActUserManager: %s has no username (uid: %d)",
1094                                    describe_user (user),
1095                                    (int) act_user_get_uid (user));
1096                 }
1097                 g_object_unref (user);
1098                 goto out;
1099         }
1100 
1101         g_debug ("ActUserManager: %s is now loaded", describe_user (user));
1102 
1103         if (username_in_exclude_list (manager, username)) {
1104                 g_debug ("ActUserManager: excluding user '%s'", username);
1105                 g_object_unref (user);
1106                 goto out;
1107         }
1108 
1109         old_user = lookup_user_by_name (manager, username);
1110 
1111         /* If username hasn't been added, yet, add it now
1112          */
1113         if (old_user == NULL) {
1114                 g_debug ("ActUserManager: %s was not yet known, adding it",
1115                          describe_user (user));
1116                 add_user (manager, user);
1117         } else {
1118                 _act_user_load_from_user (old_user, user);
1119         }
1120 
1121         g_object_unref (user);
1122 
1123 out:
1124         if (priv->new_users_inhibiting_load == NULL) {
1125                 g_debug ("ActUserManager: no pending users, trying to set loaded property");
1126                 maybe_set_is_loaded (manager);
1127         } else {
1128                 g_debug ("ActUserManager: not all users loaded yet");
1129         }
1130 }
1131 
1132 static ActUser *
find_new_user_with_object_path(ActUserManager * manager,const char * object_path)1133 find_new_user_with_object_path (ActUserManager *manager,
1134                                 const char     *object_path)
1135 {
1136         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1137         GSList *node;
1138 
1139         g_assert (object_path != NULL);
1140 
1141         for (node = priv->new_users; node != NULL; node = node->next) {
1142                 ActUser *user = ACT_USER (node->data);
1143                 const char *user_object_path = act_user_get_object_path (user);
1144                 if (g_strcmp0 (user_object_path, object_path) == 0) {
1145                         return user;
1146                 }
1147         }
1148 
1149         return NULL;
1150 }
1151 
1152 static ActUser *
add_new_user_for_object_path(const char * object_path,ActUserManager * manager)1153 add_new_user_for_object_path (const char     *object_path,
1154                               ActUserManager *manager)
1155 {
1156         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1157         ActUser *user;
1158 
1159         user = g_hash_table_lookup (priv->users_by_object_path, object_path);
1160 
1161         if (user != NULL) {
1162                 g_debug ("ActUserManager: tracking existing %s with object path %s",
1163                          describe_user (user), object_path);
1164                 return user;
1165         }
1166 
1167         user = find_new_user_with_object_path (manager, object_path);
1168 
1169         if (user != NULL) {
1170                 g_debug ("ActUserManager: tracking existing (but very recently added) %s with object path %s",
1171                          describe_user (user), object_path);
1172                 return user;
1173         }
1174 
1175         g_debug ("ActUserManager: tracking new user with object path %s", object_path);
1176 
1177         user = create_new_user (manager);
1178         _act_user_update_from_object_path (user, object_path);
1179 
1180         return user;
1181 }
1182 
1183 static void
on_new_user_in_accounts_service(GDBusProxy * proxy,const char * object_path,gpointer user_data)1184 on_new_user_in_accounts_service (GDBusProxy *proxy,
1185                                  const char *object_path,
1186                                  gpointer    user_data)
1187 {
1188         ActUserManager *manager = ACT_USER_MANAGER (user_data);
1189         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1190         g_autoptr(ActUser) user = NULL;
1191 
1192         /* Only track user changes if the user has requested a list
1193          * of users */
1194         if (!priv->list_cached_users_done) {
1195                 return;
1196         }
1197 
1198         if (!priv->is_loaded) {
1199                 g_debug ("ActUserManager: ignoring new user in accounts service with object path %s since not loaded yet", object_path);
1200                 return;
1201         }
1202 
1203         g_debug ("ActUserManager: new user in accounts service with object path %s", object_path);
1204         user = add_new_user_for_object_path (object_path, manager);
1205 }
1206 
1207 static void
on_user_removed_in_accounts_service(GDBusProxy * proxy,const char * object_path,gpointer user_data)1208 on_user_removed_in_accounts_service (GDBusProxy *proxy,
1209                                      const char *object_path,
1210                                      gpointer    user_data)
1211 {
1212         ActUserManager *manager = ACT_USER_MANAGER (user_data);
1213         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1214         ActUser        *user;
1215         GSList         *node;
1216 
1217         /* Only track user changes if the user has requested a list
1218          * of users */
1219         if (!priv->list_cached_users_done) {
1220                 return;
1221         }
1222 
1223         user = g_hash_table_lookup (priv->users_by_object_path, object_path);
1224 
1225         if (user == NULL) {
1226                 g_debug ("ActUserManager: ignoring untracked user %s", object_path);
1227                 return;
1228         } else {
1229                 g_debug ("ActUserManager: tracked user %s removed from accounts service", object_path);
1230         }
1231 
1232         node = g_slist_find (priv->new_users, user);
1233         if (node != NULL) {
1234                 g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
1235                 g_object_unref (user);
1236                 priv->new_users = g_slist_delete_link (priv->new_users, node);
1237         }
1238 
1239         remove_user (manager, user);
1240 }
1241 
1242 static void
on_get_current_session_finished(GObject * object,GAsyncResult * result,gpointer data)1243 on_get_current_session_finished (GObject        *object,
1244                                  GAsyncResult   *result,
1245                                  gpointer        data)
1246 {
1247         ConsoleKitManager *proxy = CONSOLE_KIT_MANAGER (object);
1248         g_autoptr(ActUserManager) manager = data;
1249         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1250         g_autoptr(GError) error = NULL;
1251         char              *session_id;
1252 
1253         g_assert (priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_ID);
1254 
1255         if (!console_kit_manager_call_get_current_session_finish (proxy, &session_id, result, &error)) {
1256                 if (error != NULL) {
1257                         g_debug ("Failed to identify the current session: %s",
1258                                  error->message);
1259                 } else {
1260                         g_debug ("Failed to identify the current session");
1261                 }
1262                 unload_seat (manager);
1263 
1264                 return;
1265         }
1266 
1267         priv->seat.session_id = session_id;
1268         priv->seat.state++;
1269 
1270         queue_load_seat_incrementally (manager);
1271 }
1272 
1273 #ifdef WITH_SYSTEMD
1274 static void
_get_current_systemd_session_id(ActUserManager * manager)1275 _get_current_systemd_session_id (ActUserManager *manager)
1276 {
1277         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1278         g_autofree gchar *session_id = NULL;
1279 
1280         if (!_find_graphical_systemd_session (&session_id)) {
1281                 g_debug ("Failed to identify the current session");
1282                 unload_seat (manager);
1283                 return;
1284         }
1285 
1286         priv->seat.session_id = g_strdup (session_id);
1287         priv->seat.state++;
1288 
1289         queue_load_seat_incrementally (manager);
1290 
1291 }
1292 #endif
1293 
1294 static void
get_current_session_id(ActUserManager * manager)1295 get_current_session_id (ActUserManager *manager)
1296 {
1297         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1298 
1299 #ifdef WITH_SYSTEMD
1300         if (LOGIND_RUNNING()) {
1301                 _get_current_systemd_session_id (manager);
1302                 return;
1303         }
1304 #endif
1305 
1306         if (priv->ck_manager_proxy == NULL) {
1307                 g_autoptr(GError) error = NULL;
1308 
1309                 priv->ck_manager_proxy = console_kit_manager_proxy_new_sync (priv->connection,
1310                                                                              G_DBUS_PROXY_FLAGS_NONE,
1311                                                                              CK_NAME,
1312                                                                              CK_MANAGER_PATH,
1313                                                                              NULL,
1314                                                                              &error);
1315                 if (priv->ck_manager_proxy == NULL) {
1316                         if (error != NULL) {
1317                                 g_warning ("Failed to create ConsoleKit proxy: %s", error->message);
1318                         } else {
1319                                 g_warning ("Failed to create_ConsoleKit_proxy");
1320                         }
1321                         unload_seat (manager);
1322                         return;
1323                 }
1324         }
1325 
1326         console_kit_manager_call_get_current_session (priv->ck_manager_proxy, NULL,
1327                                                       on_get_current_session_finished,
1328                                                       g_object_ref (manager));
1329 }
1330 
1331 static void
unload_new_session(ActUserManagerNewSession * new_session)1332 unload_new_session (ActUserManagerNewSession *new_session)
1333 {
1334         ActUserManager *manager = new_session->manager;
1335         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1336 
1337 	/* From here down to the check on pending_calls is idempotent,
1338 	 * like GObject dispose(); it can be called twice if the new session
1339 	 * is unloaded while there are still async calls pending.
1340 	 */
1341 
1342         if (new_session->cancellable != NULL &&
1343             !g_cancellable_is_cancelled (new_session->cancellable)) {
1344                 g_cancellable_cancel (new_session->cancellable);
1345                 g_object_unref (new_session->cancellable);
1346                 new_session->cancellable = NULL;
1347         }
1348 
1349         if (new_session->proxy != NULL) {
1350                 g_object_unref (new_session->proxy);
1351                 new_session->proxy = NULL;
1352         }
1353 
1354         g_free (new_session->x11_display);
1355         new_session->x11_display = NULL;
1356         g_free (new_session->id);
1357         new_session->id = NULL;
1358 
1359         if (manager != NULL) {
1360                 priv->new_sessions = g_slist_remove (priv->new_sessions,
1361                                                      new_session);
1362 
1363                 g_debug ("ActUserManager: unrefing manager owned by new session that's now unloaded");
1364                 new_session->manager = NULL;
1365                 g_object_unref (manager);
1366         }
1367 
1368         if (new_session->pending_calls != 0) {
1369                 /* don't "finalize" until we run out of pending calls
1370 		 * that have us as their user_data */
1371                 return;
1372         }
1373 
1374         g_slice_free (ActUserManagerNewSession, new_session);
1375 }
1376 
1377 static void
get_proxy_for_new_session(ActUserManagerNewSession * new_session)1378 get_proxy_for_new_session (ActUserManagerNewSession *new_session)
1379 {
1380         ActUserManager *manager = new_session->manager;
1381         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1382         g_autoptr(GError) error = NULL;
1383 
1384 #ifdef WITH_SYSTEMD
1385         if (LOGIND_RUNNING()) {
1386                 new_session->state++;
1387                 load_new_session_incrementally (new_session);
1388                 return;
1389         }
1390 #endif
1391 
1392         new_session->proxy = console_kit_session_proxy_new_sync (priv->connection,
1393                                                                  G_DBUS_PROXY_FLAGS_NONE,
1394                                                                  CK_NAME,
1395                                                                  new_session->id,
1396                                                                  NULL,
1397                                                                  &error);
1398         if (new_session->proxy == NULL) {
1399                 g_warning ("Failed to connect to the ConsoleKit '%s' object: %s",
1400                            new_session->id, error->message);
1401                 unload_new_session (new_session);
1402                 return;
1403         }
1404 
1405         new_session->state++;
1406 
1407         load_new_session_incrementally (new_session);
1408 }
1409 
1410 static void
on_get_unix_user_finished(GObject * object,GAsyncResult * result,gpointer data)1411 on_get_unix_user_finished (GObject      *object,
1412                            GAsyncResult *result,
1413                            gpointer      data)
1414 {
1415         ConsoleKitSession *proxy = CONSOLE_KIT_SESSION (object);
1416         ActUserManagerNewSession *new_session = data;
1417         g_autoptr(GError)  error = NULL;
1418         guint              uid;
1419 
1420         new_session->pending_calls--;
1421 
1422         if (new_session->cancellable == NULL || g_cancellable_is_cancelled (new_session->cancellable)) {
1423                 unload_new_session (new_session);
1424                 return;
1425         }
1426 
1427         if (!console_kit_session_call_get_unix_user_finish (proxy, &uid, result, &error)) {
1428                 if (error != NULL) {
1429                         g_debug ("Failed to get uid of session '%s': %s",
1430                                  new_session->id, error->message);
1431                 } else {
1432                         g_debug ("Failed to get uid of session '%s'",
1433                                  new_session->id);
1434                 }
1435                 unload_new_session (new_session);
1436                 return;
1437         }
1438 
1439         g_debug ("ActUserManager: Found uid of session '%s': %u",
1440                  new_session->id, uid);
1441 
1442         new_session->uid = (uid_t) uid;
1443         new_session->state++;
1444 
1445         load_new_session_incrementally (new_session);
1446 }
1447 
1448 #ifdef WITH_SYSTEMD
1449 static void
_get_uid_for_new_systemd_session(ActUserManagerNewSession * new_session)1450 _get_uid_for_new_systemd_session (ActUserManagerNewSession *new_session)
1451 {
1452         uid_t uid;
1453         int   res;
1454 
1455         res = sd_session_get_uid (new_session->id, &uid);
1456 
1457         if (res < 0) {
1458                 g_debug ("Failed to get uid of session '%s': %s",
1459                          new_session->id,
1460                          strerror (-res));
1461                 unload_new_session (new_session);
1462                 return;
1463         }
1464 
1465         new_session->uid = uid;
1466         new_session->state++;
1467 
1468         load_new_session_incrementally (new_session);
1469 }
1470 #endif
1471 
1472 static void
get_uid_for_new_session(ActUserManagerNewSession * new_session)1473 get_uid_for_new_session (ActUserManagerNewSession *new_session)
1474 {
1475 #ifdef WITH_SYSTEMD
1476         if (LOGIND_RUNNING()) {
1477                 _get_uid_for_new_systemd_session (new_session);
1478                 return;
1479         }
1480 #endif
1481 
1482         g_assert (new_session->proxy != NULL);
1483 
1484         new_session->pending_calls++;
1485         console_kit_session_call_get_unix_user (new_session->proxy,
1486                                                 new_session->cancellable,
1487                                                 on_get_unix_user_finished,
1488                                                 new_session);
1489 }
1490 
1491 static void
on_find_user_by_name_finished(GObject * object,GAsyncResult * result,gpointer data)1492 on_find_user_by_name_finished (GObject       *object,
1493                                GAsyncResult  *result,
1494                                gpointer       data)
1495 {
1496         AccountsAccounts *proxy = ACCOUNTS_ACCOUNTS (object);
1497         ActUserManagerFetchUserRequest *request = data;
1498         g_autoptr(GError) error = NULL;
1499         char            *user;
1500 
1501         if (!accounts_accounts_call_find_user_by_name_finish (proxy, &user, result, &error)) {
1502                 if (error != NULL) {
1503                         g_debug ("ActUserManager: Failed to find %s: %s",
1504                                  request->description, error->message);
1505                 } else {
1506                         g_debug ("ActUserManager: Failed to find %s",
1507                                  request->description);
1508                 }
1509                 give_up (request->manager, request);
1510                 return;
1511         }
1512 
1513         g_debug ("ActUserManager: Found object path of %s: %s",
1514                  request->description, user);
1515         request->object_path = user;
1516         request->state++;
1517 
1518         fetch_user_incrementally (request);
1519 }
1520 
1521 static void
on_find_user_by_id_finished(GObject * object,GAsyncResult * result,gpointer data)1522 on_find_user_by_id_finished (GObject       *object,
1523                              GAsyncResult  *result,
1524                              gpointer       data)
1525 {
1526         AccountsAccounts *proxy = ACCOUNTS_ACCOUNTS (object);
1527         ActUserManagerFetchUserRequest *request = data;
1528         g_autoptr(GError) error = NULL;
1529         char            *user;
1530 
1531         if (!accounts_accounts_call_find_user_by_id_finish (proxy, &user, result, &error)) {
1532                 if (error != NULL) {
1533                         g_debug ("ActUserManager: Failed to find user %lu: %s",
1534                                  (gulong) request->uid, error->message);
1535                 } else {
1536                         g_debug ("ActUserManager: Failed to find user with id %lu",
1537                                  (gulong) request->uid);
1538                 }
1539                 give_up (request->manager, request);
1540                 return;
1541         }
1542 
1543         g_debug ("ActUserManager: Found object path of %s: %s",
1544                  request->description, user);
1545         request->object_path = user;
1546         request->state++;
1547 
1548         fetch_user_incrementally (request);
1549 }
1550 
1551 static void
find_user_in_accounts_service(ActUserManager * manager,ActUserManagerFetchUserRequest * request)1552 find_user_in_accounts_service (ActUserManager                 *manager,
1553                                ActUserManagerFetchUserRequest *request)
1554 {
1555         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1556 
1557         g_assert (priv->accounts_proxy != NULL);
1558 
1559         g_debug ("ActUserManager: Looking for %s in accounts service",
1560                  request->description);
1561 
1562         switch (request->type) {
1563                 case ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST:
1564                     accounts_accounts_call_find_user_by_name (priv->accounts_proxy,
1565                                                               request->username,
1566                                                               NULL,
1567                                                               on_find_user_by_name_finished,
1568                                                               request);
1569                     break;
1570                 case ACT_USER_MANAGER_FETCH_USER_FROM_ID_REQUEST:
1571                     accounts_accounts_call_find_user_by_id (priv->accounts_proxy,
1572                                                             request->uid,
1573                                                             NULL,
1574                                                             on_find_user_by_id_finished,
1575                                                             request);
1576                     break;
1577 
1578         }
1579 }
1580 
1581 static void
set_is_loaded(ActUserManager * manager,gboolean is_loaded)1582 set_is_loaded (ActUserManager *manager,
1583                gboolean        is_loaded)
1584 {
1585         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1586 
1587         if (priv->is_loaded != is_loaded) {
1588                 priv->is_loaded = is_loaded;
1589                 g_object_notify (G_OBJECT (manager), "is-loaded");
1590         }
1591 }
1592 
1593 static void
load_user_paths(ActUserManager * manager,const char * const * user_paths)1594 load_user_paths (ActUserManager       *manager,
1595                  const char * const * user_paths)
1596 {
1597         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1598 
1599         /* We now have a batch of unloaded users that we know about. Once that initial
1600          * batch is loaded up, we can mark the manager as loaded.
1601          *
1602          * (see on_new_user_loaded)
1603          */
1604         if (g_strv_length ((char **) user_paths) > 0) {
1605                 int i;
1606 
1607                 g_debug ("ActUserManager: ListCachedUsers finished, will set loaded property after list is fully loaded");
1608                 for (i = 0; user_paths[i] != NULL; i++) {
1609                         ActUser *user;
1610 
1611                         user = add_new_user_for_object_path (user_paths[i], manager);
1612                         if (!priv->is_loaded) {
1613                                 priv->new_users_inhibiting_load = g_slist_prepend (priv->new_users_inhibiting_load, user);
1614                         }
1615                 }
1616         } else {
1617                 g_debug ("ActUserManager: ListCachedUsers finished with empty list, maybe setting loaded property now");
1618                 maybe_set_is_loaded (manager);
1619         }
1620 }
1621 
1622 static void
load_included_usernames(ActUserManager * manager)1623 load_included_usernames (ActUserManager *manager)
1624 {
1625         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1626         GSList *l;
1627 
1628         /* Add users who are specifically included */
1629         for (l = priv->include_usernames; l != NULL; l = l->next) {
1630                 g_debug ("ActUserManager: Adding included user %s", (char *)l->data);
1631 
1632                 load_user (manager, l->data);
1633         }
1634 }
1635 
1636 static void
on_get_x11_display_finished(GObject * object,GAsyncResult * result,gpointer data)1637 on_get_x11_display_finished (GObject      *object,
1638                              GAsyncResult *result,
1639                              gpointer      data)
1640 {
1641         ConsoleKitSession *proxy = CONSOLE_KIT_SESSION (object);
1642         ActUserManagerNewSession *new_session = data;
1643         g_autoptr(GError) error = NULL;
1644         char              *x11_display;
1645 
1646         new_session->pending_calls--;
1647 
1648         if (new_session->cancellable == NULL || g_cancellable_is_cancelled (new_session->cancellable)) {
1649                 unload_new_session (new_session);
1650                 return;
1651         }
1652 
1653         if (!console_kit_session_call_get_x11_display_finish (proxy, &x11_display, result, &error)) {
1654                 if (error != NULL) {
1655                         g_debug ("Failed to get the x11 display of session '%s': %s",
1656                                  new_session->id, error->message);
1657                 } else {
1658                         g_debug ("Failed to get the x11 display of session '%s'",
1659                                  new_session->id);
1660                 }
1661                 unload_new_session (new_session);
1662                 return;
1663         }
1664 
1665         g_debug ("ActUserManager: Found x11 display of session '%s': %s",
1666                  new_session->id, x11_display);
1667 
1668         new_session->x11_display = x11_display;
1669         new_session->state++;
1670 
1671         load_new_session_incrementally (new_session);
1672 }
1673 
1674 #ifdef WITH_SYSTEMD
1675 static void
_get_x11_display_for_new_systemd_session(ActUserManagerNewSession * new_session)1676 _get_x11_display_for_new_systemd_session (ActUserManagerNewSession *new_session)
1677 {
1678         g_autofree gchar *session_type = NULL;
1679         g_autofree gchar *x11_display = NULL;
1680         int res;
1681 
1682         res = sd_session_get_type (new_session->id,
1683                                    &session_type);
1684         if (res < 0) {
1685                 g_debug ("ActUserManager: Failed to get the type of session '%s': %s",
1686                          new_session->id,
1687                          strerror (-res));
1688                 unload_new_session (new_session);
1689                 return;
1690         }
1691 
1692         if (g_strcmp0 (session_type, "x11") != 0 &&
1693             g_strcmp0 (session_type, "wayland") != 0) {
1694                 g_debug ("ActUserManager: (mostly) ignoring %s session '%s' since it's not graphical",
1695                          session_type,
1696                          new_session->id);
1697                 x11_display = NULL;
1698                 goto done;
1699         }
1700 
1701         res = sd_session_get_display (new_session->id,
1702                                       &x11_display);
1703         if (res < 0) {
1704                 g_debug ("ActUserManager: Failed to get the x11 display of session '%s': %s",
1705                          new_session->id,
1706                          strerror (-res));
1707                 g_debug ("ActUserManager: Treating X11 display as blank");
1708                 x11_display = strdup ("");
1709         } else {
1710                 g_debug ("ActUserManager: Found x11 display of session '%s': %s",
1711                          new_session->id, x11_display);
1712         }
1713 
1714  done:
1715         new_session->x11_display = g_strdup (x11_display);
1716         new_session->state++;
1717 
1718         load_new_session_incrementally (new_session);
1719 }
1720 #endif
1721 
1722 static void
get_x11_display_for_new_session(ActUserManagerNewSession * new_session)1723 get_x11_display_for_new_session (ActUserManagerNewSession *new_session)
1724 {
1725 #ifdef WITH_SYSTEMD
1726         if (LOGIND_RUNNING()) {
1727                 _get_x11_display_for_new_systemd_session (new_session);
1728                 return;
1729         }
1730 #endif
1731 
1732         g_assert (new_session->proxy != NULL);
1733 
1734         new_session->pending_calls++;
1735         console_kit_session_call_get_x11_display (new_session->proxy,
1736                                                   new_session->cancellable,
1737                                                   on_get_x11_display_finished,
1738                                                   new_session);
1739 }
1740 
1741 static void
maybe_add_new_session(ActUserManagerNewSession * new_session)1742 maybe_add_new_session (ActUserManagerNewSession *new_session)
1743 {
1744         ActUserManager *manager;
1745         ActUser        *user;
1746         gboolean        is_ours;
1747 
1748         manager = ACT_USER_MANAGER (new_session->manager);
1749 
1750         is_ours = TRUE;
1751 
1752         if (new_session->x11_display == NULL) {
1753                 g_debug ("AcUserManager: (mostly) ignoring session '%s' since it's not graphical",
1754                          new_session->id);
1755                 is_ours = FALSE;
1756         } else if (session_is_login_window (manager, new_session->id)) {
1757                 new_session->state = ACT_USER_MANAGER_NEW_SESSION_STATE_LOADED;
1758                 unload_new_session (new_session);
1759                 return;
1760         } else if (!session_is_on_our_seat (manager, new_session->id)) {
1761                 is_ours = FALSE;
1762         }
1763 
1764         user = act_user_manager_get_user_by_id (manager, new_session->uid);
1765         if (user == NULL) {
1766                 unload_new_session (new_session);
1767                 return;
1768         }
1769 
1770         add_session_for_user (manager, user, new_session->id, is_ours);
1771 }
1772 
1773 static void
load_new_session(ActUserManager * manager,const char * session_id)1774 load_new_session (ActUserManager *manager,
1775                   const char     *session_id)
1776 {
1777         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1778         ActUserManagerNewSession *new_session;
1779 
1780         new_session = g_slice_new0 (ActUserManagerNewSession);
1781 
1782         new_session->manager = g_object_ref (manager);
1783         new_session->id = g_strdup (session_id);
1784         new_session->state = ACT_USER_MANAGER_NEW_SESSION_STATE_UNLOADED + 1;
1785         new_session->cancellable = g_cancellable_new ();
1786 
1787         priv->new_sessions = g_slist_prepend (priv->new_sessions, new_session);
1788         load_new_session_incrementally (new_session);
1789 }
1790 
1791 static void
seat_session_added(GDBusProxy * seat_proxy,const char * session_id,ActUserManager * manager)1792 seat_session_added (GDBusProxy     *seat_proxy,
1793                     const char     *session_id,
1794                     ActUserManager *manager)
1795 {
1796         g_debug ("ActUserManager: Session added: %s", session_id);
1797 
1798         load_new_session (manager, session_id);
1799 }
1800 
1801 static gint
match_new_session_cmpfunc(gconstpointer a,gconstpointer b)1802 match_new_session_cmpfunc (gconstpointer a,
1803                            gconstpointer b)
1804 {
1805         ActUserManagerNewSession *new_session;
1806         const char               *session_id;
1807 
1808         new_session = (ActUserManagerNewSession *) a;
1809         session_id = (const char *) b;
1810 
1811         return strcmp (new_session->id, session_id);
1812 }
1813 
1814 static void
_remove_session(ActUserManager * manager,const char * session_id)1815 _remove_session (ActUserManager *manager,
1816                  const char     *session_id)
1817 {
1818         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1819         ActUser       *user;
1820         GSList        *found;
1821 
1822         g_debug ("ActUserManager: Session removed: %s", session_id);
1823 
1824         found = g_slist_find_custom (priv->new_sessions,
1825                                      session_id,
1826                                      match_new_session_cmpfunc);
1827 
1828         if (found != NULL) {
1829                 ActUserManagerNewSession *new_session;
1830 
1831                 new_session = (ActUserManagerNewSession *) found->data;
1832 
1833                 if (new_session->state > ACT_USER_MANAGER_NEW_SESSION_STATE_GET_X11_DISPLAY) {
1834                         g_debug ("ActUserManager: New session for uid %d on "
1835                                  "x11 display %s removed before fully loading",
1836                                  (int) new_session->uid, new_session->x11_display);
1837                 } else if (new_session->state > ACT_USER_MANAGER_NEW_SESSION_STATE_GET_UID) {
1838                         g_debug ("ActUserManager: New session for uid %d "
1839                                  "removed before fully loading",
1840                                  (int) new_session->uid);
1841                 } else {
1842                         g_debug ("ActUserManager: New session removed "
1843                                  "before fully loading");
1844                 }
1845                 unload_new_session (new_session);
1846                 return;
1847         }
1848 
1849         /* since the session object may already be gone
1850          * we can't query CK directly */
1851 
1852         user = g_hash_table_lookup (priv->sessions, session_id);
1853 
1854         if (user == NULL) {
1855                 /* nothing to do */
1856                 return;
1857         }
1858 
1859         g_debug ("ActUserManager: Session removed for %s", describe_user (user));
1860         _act_user_remove_session (user, session_id);
1861         g_hash_table_remove (priv->sessions, session_id);
1862 }
1863 
1864 static void
seat_session_removed(GDBusProxy * seat_proxy,const char * session_id,ActUserManager * manager)1865 seat_session_removed (GDBusProxy     *seat_proxy,
1866                       const char     *session_id,
1867                       ActUserManager *manager)
1868 {
1869         _remove_session (manager, session_id);
1870 }
1871 
1872 #ifdef WITH_SYSTEMD
1873 
1874 static gboolean
_session_recognized(ActUserManager * manager,const char * session_id)1875 _session_recognized (ActUserManager *manager,
1876                      const char     *session_id)
1877 {
1878         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1879         GSList *node;
1880 
1881         if (g_hash_table_contains (priv->sessions, session_id)) {
1882                 return TRUE;
1883         }
1884 
1885         node = priv->new_sessions;
1886         while (node != NULL) {
1887                 ActUserManagerNewSession *new_session = node->data;
1888 
1889                 if (g_strcmp0 (new_session->id, session_id) == 0) {
1890                         return TRUE;
1891                 }
1892 
1893                 node = node->next;
1894         }
1895         return FALSE;
1896 }
1897 
1898 static void
_add_systemd_session(ActUserManager * manager,const char * session_id)1899 _add_systemd_session (ActUserManager *manager,
1900                       const char     *session_id)
1901 {
1902         load_new_session (manager, session_id);
1903 }
1904 
1905 static void
_add_new_systemd_sessions(ActUserManager * manager,GHashTable * systemd_sessions)1906 _add_new_systemd_sessions (ActUserManager *manager,
1907                            GHashTable     *systemd_sessions)
1908 {
1909         GHashTableIter iter;
1910         gpointer key, value;
1911 
1912         g_hash_table_iter_init (&iter, systemd_sessions);
1913         while (g_hash_table_iter_next (&iter, &key, &value)) {
1914                 char *session_id = key;
1915 
1916                 if (!_session_recognized (manager, session_id)) {
1917                         _add_systemd_session (manager, session_id);
1918                 }
1919         }
1920 }
1921 
1922 static void
_remove_systemd_session(ActUserManager * manager,const char * session_id)1923 _remove_systemd_session (ActUserManager *manager,
1924                          const char     *session_id)
1925 {
1926         _remove_session (manager, session_id);
1927 }
1928 
1929 static void
_remove_stale_systemd_sessions(ActUserManager * manager,GHashTable * systemd_sessions)1930 _remove_stale_systemd_sessions (ActUserManager *manager,
1931                                 GHashTable     *systemd_sessions)
1932 {
1933         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
1934         GHashTableIter iter;
1935         gpointer key, value;
1936         GSList *node, *sessions_to_remove;
1937 
1938         sessions_to_remove = NULL;
1939         g_hash_table_iter_init (&iter, priv->sessions);
1940         while (g_hash_table_iter_next (&iter, &key, &value)) {
1941                 char *session_id = key;
1942 
1943                 if (g_hash_table_contains (systemd_sessions, session_id)) {
1944                         continue;
1945                 }
1946 
1947                 sessions_to_remove = g_slist_prepend (sessions_to_remove, session_id);
1948         }
1949 
1950         node = priv->new_sessions;
1951         while (node != NULL) {
1952                 ActUserManagerNewSession *new_session = node->data;
1953                 node = node->next;
1954 
1955                 if (g_hash_table_contains (systemd_sessions, new_session->id)) {
1956                         continue;
1957                 }
1958 
1959                 sessions_to_remove = g_slist_prepend (sessions_to_remove, new_session->id);
1960         }
1961 
1962         node = sessions_to_remove;
1963         while (node != NULL) {
1964                 char *session_id = node->data;
1965                 GSList *next_node = node->next;
1966 
1967                 _remove_systemd_session (manager, session_id);
1968 
1969                 node = next_node;
1970         }
1971 
1972         g_slist_free (sessions_to_remove);
1973 }
1974 
1975 #ifdef WITH_SYSTEMD
1976 static void
reload_systemd_sessions(ActUserManager * manager)1977 reload_systemd_sessions (ActUserManager *manager)
1978 {
1979         int         res;
1980         int         i;
1981         g_auto(GStrv) sessions = NULL;
1982         g_autoptr(GHashTable) systemd_sessions = NULL;
1983 
1984         res = sd_get_sessions (&sessions);
1985         if (res < 0) {
1986                 g_debug ("Failed to determine sessions: %s", strerror (-res));
1987                 return;
1988         }
1989 
1990         systemd_sessions = g_hash_table_new (g_str_hash,
1991                                              g_str_equal);
1992 
1993         if (sessions != NULL) {
1994                 for (i = 0; sessions[i] != NULL; i ++) {
1995                         g_autofree gchar *state = NULL;
1996                         g_autofree gchar *session_class = NULL;
1997 
1998                         res = sd_session_get_state (sessions[i], &state);
1999                         if (res < 0) {
2000                                 g_debug ("Failed to determine state of session %s: %s", sessions[i], strerror (-res));
2001                                 continue;
2002                         }
2003 
2004                         if (g_strcmp0 (state, "closing") == 0) {
2005                                 continue;
2006                         }
2007 
2008                         res = sd_session_get_class (sessions[i], &session_class);
2009                         if (res < 0) {
2010                                 g_debug ("Failed to determine class of session %s: %s", sessions[i], strerror (-res));
2011                                 continue;
2012                         }
2013 
2014                         if (g_strcmp0 (session_class, "user") != 0) {
2015                                 g_debug ("Ignoring non-user session %s (class %s)", sessions[i], session_class);
2016                                 continue;
2017                         }
2018 
2019                         g_hash_table_insert (systemd_sessions,
2020                                              sessions[i], NULL);
2021                 }
2022 
2023         }
2024 
2025         _add_new_systemd_sessions (manager, systemd_sessions);
2026         _remove_stale_systemd_sessions (manager, systemd_sessions);
2027 }
2028 
2029 #endif
2030 static gboolean
on_session_monitor_event(GPollableInputStream * stream,ActUserManager * manager)2031 on_session_monitor_event (GPollableInputStream *stream,
2032                           ActUserManager       *manager)
2033 {
2034         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2035         sd_login_monitor_flush (priv->seat.session_monitor);
2036         reload_systemd_sessions (manager);
2037         return TRUE;
2038 }
2039 
2040 static void
_monitor_for_systemd_session_changes(ActUserManager * manager)2041 _monitor_for_systemd_session_changes (ActUserManager *manager)
2042 {
2043         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2044         int res;
2045         int fd;
2046         GSource *source;
2047 
2048         res = sd_login_monitor_new ("session", &priv->seat.session_monitor);
2049 
2050         if (res < 0) {
2051                 g_warning ("Failed to monitor logind session changes: %s",
2052                            strerror (-res));
2053                 unload_seat (manager);
2054                 return;
2055         }
2056 
2057         fd = sd_login_monitor_get_fd (priv->seat.session_monitor);
2058 
2059         priv->seat.session_monitor_stream = g_unix_input_stream_new (fd, FALSE);
2060         source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->seat.session_monitor_stream),
2061                                                         NULL);
2062         g_source_set_callback (source,
2063                                (GSourceFunc)
2064                                on_session_monitor_event,
2065                                manager,
2066                                NULL);
2067         priv->seat.session_monitor_source_id = g_source_attach (source, NULL);
2068         g_source_unref (source);
2069 }
2070 #endif
2071 
2072 static void
get_seat_proxy(ActUserManager * manager)2073 get_seat_proxy (ActUserManager *manager)
2074 {
2075         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2076         g_autoptr(GError) error = NULL;
2077 
2078 #ifdef WITH_SYSTEMD
2079         if (LOGIND_RUNNING()) {
2080                 _monitor_for_systemd_session_changes (manager);
2081                 priv->seat.state++;
2082                 return;
2083         }
2084 #endif
2085 
2086         g_assert (priv->seat.seat_proxy == NULL);
2087 
2088         priv->seat.seat_proxy = console_kit_seat_proxy_new_sync (priv->connection,
2089                                                                  G_DBUS_PROXY_FLAGS_NONE,
2090                                                                  CK_NAME,
2091                                                                  priv->seat.id,
2092                                                                  NULL,
2093                                                                  &error);
2094         if (priv->seat.seat_proxy == NULL) {
2095                 if (error != NULL) {
2096                         g_warning ("Failed to connect to the ConsoleKit seat object: %s",
2097                                    error->message);
2098                 } else {
2099                         g_warning ("Failed to connect to the ConsoleKit seat object");
2100                 }
2101                 unload_seat (manager);
2102                 return;
2103         }
2104 
2105         g_signal_connect (priv->seat.seat_proxy,
2106                           "session-added",
2107                           G_CALLBACK (seat_session_added),
2108                           manager);
2109         g_signal_connect (priv->seat.seat_proxy,
2110                           "session-removed",
2111                           G_CALLBACK (seat_session_removed),
2112                           manager);
2113         priv->seat.state++;
2114 }
2115 
2116 static void
on_console_kit_session_proxy_gotten(GObject * object,GAsyncResult * result,gpointer user_data)2117 on_console_kit_session_proxy_gotten (GObject *object, GAsyncResult *result, gpointer user_data)
2118 {
2119         ActUserManager *manager = user_data;
2120         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2121         g_autoptr(GError) error = NULL;
2122 
2123         g_debug ("on_console_kit_session_proxy_gotten");
2124 
2125         priv->seat.session_proxy = console_kit_session_proxy_new_finish (result, &error);
2126 
2127         if (priv->seat.session_proxy == NULL) {
2128                 if (error != NULL) {
2129                         g_warning ("Failed to connect to the ConsoleKit session object: %s",
2130                                    error->message);
2131                 } else {
2132                         g_warning ("Failed to connect to the ConsoleKit session object");
2133                 }
2134                 unload_seat (manager);
2135 
2136                 goto out;
2137         }
2138 
2139         priv->seat.state++;
2140         load_seat_incrementally (manager);
2141 
2142  out:
2143         g_debug ("ActUserManager: unrefing manager owned by ConsoleKit proxy getter");
2144         g_object_unref (manager);
2145 }
2146 
2147 static void
get_session_proxy(ActUserManager * manager)2148 get_session_proxy (ActUserManager *manager)
2149 {
2150         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2151 
2152 #ifdef WITH_SYSTEMD
2153         if (LOGIND_RUNNING()) {
2154                 priv->seat.state++;
2155                 queue_load_seat_incrementally (manager);
2156                 return;
2157         }
2158 #endif
2159 
2160         g_debug ("ActUserManager: fetching user proxy");
2161 
2162         g_assert (priv->seat.session_proxy == NULL);
2163 
2164         console_kit_session_proxy_new (priv->connection,
2165                                        G_DBUS_PROXY_FLAGS_NONE,
2166                                        CK_NAME,
2167                                        priv->seat.session_id,
2168                                        NULL,
2169                                        on_console_kit_session_proxy_gotten,
2170                                        g_object_ref (manager));
2171 }
2172 
2173 static void
unload_seat(ActUserManager * manager)2174 unload_seat (ActUserManager *manager)
2175 {
2176         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2177 
2178         priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED;
2179 
2180         if (priv->seat.seat_proxy != NULL) {
2181                 g_object_unref (priv->seat.seat_proxy);
2182                 priv->seat.seat_proxy = NULL;
2183         }
2184 
2185         if (priv->seat.session_proxy != NULL) {
2186                 g_object_unref (priv->seat.session_proxy);
2187                 priv->seat.session_proxy = NULL;
2188         }
2189 
2190         g_free (priv->seat.id);
2191         priv->seat.id = NULL;
2192 
2193         g_free (priv->seat.session_id);
2194         priv->seat.session_id = NULL;
2195 
2196         g_debug ("ActUserManager: seat unloaded, so trying to set loaded property");
2197         maybe_set_is_loaded (manager);
2198 }
2199 
2200 static void
load_new_session_incrementally(ActUserManagerNewSession * new_session)2201 load_new_session_incrementally (ActUserManagerNewSession *new_session)
2202 {
2203         switch (new_session->state) {
2204         case ACT_USER_MANAGER_NEW_SESSION_STATE_GET_PROXY:
2205                 get_proxy_for_new_session (new_session);
2206                 break;
2207         case ACT_USER_MANAGER_NEW_SESSION_STATE_GET_UID:
2208                 get_uid_for_new_session (new_session);
2209                 break;
2210         case ACT_USER_MANAGER_NEW_SESSION_STATE_GET_X11_DISPLAY:
2211                 get_x11_display_for_new_session (new_session);
2212                 break;
2213         case ACT_USER_MANAGER_NEW_SESSION_STATE_MAYBE_ADD:
2214                 maybe_add_new_session (new_session);
2215                 break;
2216         case ACT_USER_MANAGER_NEW_SESSION_STATE_LOADED:
2217                 break;
2218         default:
2219                 g_assert_not_reached ();
2220         }
2221 }
2222 
2223 static void
free_fetch_user_request(ActUserManagerFetchUserRequest * request)2224 free_fetch_user_request (ActUserManagerFetchUserRequest *request)
2225 {
2226         ActUserManager *manager = request->manager;
2227         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2228 
2229         g_object_set_data (G_OBJECT (request->user), "fetch-user-request", NULL);
2230 
2231         priv->fetch_user_requests = g_slist_remove (priv->fetch_user_requests, request);
2232         if (request->type == ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST) {
2233                 g_free (request->username);
2234         }
2235 
2236         g_free (request->object_path);
2237         g_free (request->description);
2238         g_debug ("ActUserManager: unrefing manager owned by fetch user request");
2239         g_object_unref (manager);
2240 
2241         g_slice_free (ActUserManagerFetchUserRequest, request);
2242 }
2243 
2244 static void
give_up(ActUserManager * manager,ActUserManagerFetchUserRequest * request)2245 give_up (ActUserManager                 *manager,
2246          ActUserManagerFetchUserRequest *request)
2247 {
2248         if (request->type == ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST)
2249                 g_debug ("ActUserManager: failed to load user %s", request->username);
2250         else
2251                 g_debug ("ActUserManager: failed to load user %lu", (gulong) request->uid);
2252 
2253         request->state = ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED;
2254 
2255         if (request->user)
2256                 _act_user_update_as_nonexistent (request->user);
2257 }
2258 
2259 static void
on_user_manager_maybe_ready_for_request(ActUserManager * manager,GParamSpec * pspec,ActUserManagerFetchUserRequest * request)2260 on_user_manager_maybe_ready_for_request (ActUserManager                 *manager,
2261                                          GParamSpec                     *pspec,
2262                                          ActUserManagerFetchUserRequest *request)
2263 {
2264         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2265 
2266         if (!priv->is_loaded) {
2267                 return;
2268         }
2269 
2270         g_debug ("ActUserManager: user manager now loaded, proceeding with fetch user request for %s",
2271                  request->description);
2272 
2273         g_signal_handlers_disconnect_by_func (manager, on_user_manager_maybe_ready_for_request, request);
2274 
2275         request->state++;
2276         fetch_user_incrementally (request);
2277 }
2278 
2279 static void
fetch_user_incrementally(ActUserManagerFetchUserRequest * request)2280 fetch_user_incrementally (ActUserManagerFetchUserRequest *request)
2281 {
2282         ActUserManager *manager = request->manager;
2283         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2284 
2285         g_debug ("ActUserManager: finding %s state %d",
2286                  request->description, request->state);
2287         switch (request->state) {
2288         case ACT_USER_MANAGER_GET_USER_STATE_WAIT_FOR_LOADED:
2289                 if (priv->is_loaded) {
2290                         request->state++;
2291                         fetch_user_incrementally (request);
2292                 } else {
2293                         g_debug ("ActUserManager: waiting for user manager to load before finding %s",
2294                                  request->description);
2295                         g_signal_connect (manager, "notify::is-loaded",
2296                                           G_CALLBACK (on_user_manager_maybe_ready_for_request), request);
2297 
2298                 }
2299                 break;
2300 
2301         case ACT_USER_MANAGER_GET_USER_STATE_ASK_ACCOUNTS_SERVICE:
2302                 if (priv->accounts_proxy == NULL) {
2303                         give_up (manager, request);
2304                 } else {
2305                         find_user_in_accounts_service (manager, request);
2306                 }
2307                 break;
2308         case ACT_USER_MANAGER_GET_USER_STATE_FETCHED:
2309                 g_debug ("ActUserManager: %s fetched", request->description);
2310                 _act_user_update_from_object_path (request->user, request->object_path);
2311                 break;
2312         case ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED:
2313                 g_debug ("ActUserManager: %s was not fetched", request->description);
2314                 break;
2315         default:
2316                 g_assert_not_reached ();
2317         }
2318 
2319         if (request->state == ACT_USER_MANAGER_GET_USER_STATE_FETCHED  ||
2320             request->state == ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED) {
2321                 g_debug ("ActUserManager: finished handling request for %s",
2322                          request->description);
2323                 free_fetch_user_request (request);
2324         }
2325 }
2326 
2327 static void
fetch_user_with_username_from_accounts_service(ActUserManager * manager,ActUser * user,const char * username)2328 fetch_user_with_username_from_accounts_service (ActUserManager *manager,
2329                                                 ActUser        *user,
2330                                                 const char     *username)
2331 {
2332         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2333         ActUserManagerFetchUserRequest *request;
2334 
2335         request = g_slice_new0 (ActUserManagerFetchUserRequest);
2336 
2337         request->manager = g_object_ref (manager);
2338         request->type = ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST;
2339         request->username = g_strdup (username);
2340         request->user = user;
2341         request->state = ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED + 1;
2342         request->description = g_strdup_printf ("user '%s'", request->username);
2343 
2344         priv->fetch_user_requests = g_slist_prepend (priv->fetch_user_requests,
2345                                                      request);
2346         g_object_set_data (G_OBJECT (user), "fetch-user-request", request);
2347         fetch_user_incrementally (request);
2348 }
2349 
2350 static void
fetch_user_with_id_from_accounts_service(ActUserManager * manager,ActUser * user,uid_t id)2351 fetch_user_with_id_from_accounts_service (ActUserManager *manager,
2352                                           ActUser        *user,
2353                                           uid_t           id)
2354 {
2355         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2356         ActUserManagerFetchUserRequest *request;
2357 
2358         request = g_slice_new0 (ActUserManagerFetchUserRequest);
2359 
2360         request->manager = g_object_ref (manager);
2361         request->type = ACT_USER_MANAGER_FETCH_USER_FROM_ID_REQUEST;
2362         request->uid = id;
2363         request->user = user;
2364         request->state = ACT_USER_MANAGER_GET_USER_STATE_UNFETCHED + 1;
2365         request->description = g_strdup_printf ("user with id %lu", (gulong) request->uid);
2366 
2367         priv->fetch_user_requests = g_slist_prepend (priv->fetch_user_requests,
2368                                                      request);
2369         g_object_set_data (G_OBJECT (user), "fetch-user-request", request);
2370         fetch_user_incrementally (request);
2371 }
2372 
2373 /**
2374  * act_user_manager_get_user:
2375  * @manager: the manager to query.
2376  * @username: the login name of the user to get.
2377  *
2378  * Retrieves a pointer to the #ActUser object for the login @username
2379  * from @manager. Trying to use this object before its
2380  * #ActUser:is-loaded property is %TRUE will result in undefined
2381  * behavior.
2382  *
2383  * Returns: (transfer none): #ActUser object
2384  **/
2385 ActUser *
act_user_manager_get_user(ActUserManager * manager,const char * username)2386 act_user_manager_get_user (ActUserManager *manager,
2387                            const char     *username)
2388 {
2389         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2390         ActUser *user;
2391 
2392         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
2393         g_return_val_if_fail (username != NULL && username[0] != '\0', NULL);
2394 
2395         user = lookup_user_by_name (manager, username);
2396 
2397         /* if we don't have it loaded try to load it now */
2398         if (user == NULL) {
2399                 g_debug ("ActUserManager: trying to track new user with username %s", username);
2400                 user = create_new_user (manager);
2401 
2402                 if (priv->accounts_proxy != NULL) {
2403                         fetch_user_with_username_from_accounts_service (manager, user, username);
2404                 }
2405         }
2406 
2407         return user;
2408 }
2409 
2410 static void
load_user(ActUserManager * manager,const char * username)2411 load_user (ActUserManager *manager,
2412            const char     *username)
2413 {
2414         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2415         ActUser *user;
2416         g_autoptr(GError) error = NULL;
2417         char *object_path = NULL;
2418         gboolean user_found;
2419 
2420         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
2421         g_return_if_fail (username != NULL && username[0] != '\0');
2422 
2423         user = lookup_user_by_name (manager, username);
2424 
2425         if (user == NULL) {
2426                 g_debug ("ActUserManager: trying to track new user with username %s", username);
2427                 user = create_new_user (manager);
2428         }
2429 
2430         user_found = accounts_accounts_call_find_user_by_name_sync (priv->accounts_proxy,
2431                                                                     username,
2432                                                                     &object_path,
2433                                                                     NULL,
2434                                                                     &error);
2435 
2436         if (!user_found) {
2437                 if (error != NULL) {
2438                         g_debug ("ActUserManager: Failed to find user '%s': %s",
2439                                  username, error->message);
2440                 } else {
2441                         g_debug ("ActUserManager: Failed to find user '%s'",
2442                                  username);
2443                 }
2444         }
2445 
2446         _act_user_update_from_object_path (user, object_path);
2447 }
2448 
2449 /**
2450  * act_user_manager_get_user_by_id:
2451  * @manager: the manager to query.
2452  * @id: the uid of the user to get.
2453  *
2454  * Retrieves a pointer to the #ActUser object for the user with the
2455  * given uid from @manager. Trying to use this object before its
2456  * #ActUser:is-loaded property is %TRUE will result in undefined
2457  * behavior.
2458  *
2459  * Returns: (transfer none): #ActUser object
2460  */
2461 ActUser *
act_user_manager_get_user_by_id(ActUserManager * manager,uid_t id)2462 act_user_manager_get_user_by_id (ActUserManager *manager,
2463                                  uid_t           id)
2464 {
2465         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2466         ActUser *user;
2467         g_autofree gchar *object_path = NULL;
2468 
2469         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
2470 
2471         object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%lu", (gulong) id);
2472         user = g_hash_table_lookup (priv->users_by_object_path, object_path);
2473 
2474         if (user != NULL) {
2475                 return g_object_ref (user);
2476         } else {
2477                 g_debug ("ActUserManager: trying to track new user with uid %lu", (gulong) id);
2478                 user = create_new_user (manager);
2479 
2480                 if (priv->accounts_proxy != NULL) {
2481                         fetch_user_with_id_from_accounts_service (manager, user, id);
2482                 }
2483         }
2484 
2485         return user;
2486 }
2487 
2488 static void
listify_hash_values_hfunc(gpointer key,gpointer value,gpointer user_data)2489 listify_hash_values_hfunc (gpointer key,
2490                            gpointer value,
2491                            gpointer user_data)
2492 {
2493         GSList **list = user_data;
2494 
2495         *list = g_slist_prepend (*list, value);
2496 }
2497 
2498 /**
2499  * act_user_manager_list_users:
2500  * @manager: a #ActUserManager
2501  *
2502  * Get a list of system user accounts
2503  *
2504  * Returns: (element-type ActUser) (transfer container): List of #ActUser objects
2505  */
2506 GSList *
act_user_manager_list_users(ActUserManager * manager)2507 act_user_manager_list_users (ActUserManager *manager)
2508 {
2509         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2510         GSList *retval;
2511 
2512         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), NULL);
2513 
2514         if (!priv->list_cached_users_done) {
2515                 load_users (manager);
2516 
2517                 if (priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY)
2518                         queue_load_seat_incrementally (manager);
2519         }
2520 
2521         retval = NULL;
2522         g_hash_table_foreach (priv->normal_users_by_name, listify_hash_values_hfunc, &retval);
2523 
2524         return g_slist_sort (retval, (GCompareFunc) act_user_collate);
2525 }
2526 
2527 static void
maybe_set_is_loaded(ActUserManager * manager)2528 maybe_set_is_loaded (ActUserManager *manager)
2529 {
2530         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2531 
2532         if (priv->is_loaded) {
2533                 g_debug ("ActUserManager: already loaded, so not setting loaded property");
2534                 return;
2535         }
2536 
2537         if (priv->getting_sessions) {
2538                 g_debug ("ActUserManager: GetSessions call pending, so not setting loaded property");
2539                 return;
2540         }
2541 
2542         if (priv->new_users_inhibiting_load != NULL) {
2543                 g_debug ("ActUserManager: Loading new users, so not setting loaded property");
2544                 return;
2545         }
2546 
2547         /* Don't set is_loaded yet unless the seat is already loaded enough
2548          * or failed to load.
2549          */
2550         if (priv->seat.state >= ACT_USER_MANAGER_SEAT_STATE_GET_ID) {
2551                 g_debug ("ActUserManager: Seat loaded, so now setting loaded property");
2552         } else if (priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_UNLOADED) {
2553                 g_debug ("ActUserManager: Seat wouldn't load, so giving up on it and setting loaded property");
2554         } else {
2555                 g_debug ("ActUserManager: Seat still actively loading, so not setting loaded property");
2556                 return;
2557         }
2558 
2559         set_is_loaded (manager, TRUE);
2560 }
2561 
2562 
2563 static GSList *
slist_deep_copy(const GSList * list)2564 slist_deep_copy (const GSList *list)
2565 {
2566         GSList *retval;
2567         GSList *l;
2568 
2569         if (list == NULL)
2570                 return NULL;
2571 
2572         retval = g_slist_copy ((GSList *) list);
2573         for (l = retval; l != NULL; l = l->next) {
2574                 l->data = g_strdup (l->data);
2575         }
2576 
2577         return retval;
2578 }
2579 
2580 static void
on_get_sessions_finished(GObject * object,GAsyncResult * result,gpointer data)2581 on_get_sessions_finished (GObject      *object,
2582                           GAsyncResult *result,
2583                           gpointer      data)
2584 {
2585         ConsoleKitSeat *proxy = CONSOLE_KIT_SEAT (object);
2586         g_autoptr(ActUserManager) manager = data;
2587         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2588         g_autoptr(GError) error = NULL;
2589         g_auto(GStrv) session_ids = NULL;
2590         int             i;
2591 
2592         if (!console_kit_seat_call_get_sessions_finish (proxy, &session_ids, result, &error)) {
2593                 if (error != NULL) {
2594                         g_warning ("unable to determine sessions for seat: %s",
2595                                    error->message);
2596                 } else {
2597                         g_warning ("unable to determine sessions for seat");
2598                 }
2599 
2600                 return;
2601         }
2602 
2603         priv->getting_sessions = FALSE;
2604         for (i = 0; session_ids[i] != NULL; i++) {
2605                 load_new_session (manager, session_ids[i]);
2606         }
2607 
2608         g_debug ("ActUserManager: GetSessions call finished, so trying to set loaded property");
2609         maybe_set_is_loaded (manager);
2610 }
2611 
2612 static void
load_console_kit_sessions(ActUserManager * manager)2613 load_console_kit_sessions (ActUserManager *manager)
2614 {
2615         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2616 
2617         if (priv->seat.seat_proxy == NULL) {
2618                 g_debug ("ActUserManager: no seat proxy; can't load sessions");
2619                 return;
2620         }
2621 
2622         priv->getting_sessions = TRUE;
2623         console_kit_seat_call_get_sessions (priv->seat.seat_proxy,
2624                                             NULL,
2625                                             on_get_sessions_finished,
2626                                             g_object_ref (manager));
2627 }
2628 
2629 static void
load_sessions(ActUserManager * manager)2630 load_sessions (ActUserManager *manager)
2631 {
2632 #ifdef WITH_SYSTEMD
2633         if (LOGIND_RUNNING()) {
2634                 reload_systemd_sessions (manager);
2635                 maybe_set_is_loaded (manager);
2636                 return;
2637         }
2638 #endif
2639         load_console_kit_sessions (manager);
2640 }
2641 
2642 static void
load_users(ActUserManager * manager)2643 load_users (ActUserManager *manager)
2644 {
2645         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2646         g_autoptr(GError) error = NULL;
2647         g_auto(GStrv) user_paths = NULL;
2648         gboolean could_list = FALSE;
2649 
2650         if (!ensure_accounts_proxy (manager)) {
2651                 return;
2652         }
2653 
2654         g_debug ("ActUserManager: calling 'ListCachedUsers'");
2655 
2656         could_list = accounts_accounts_call_list_cached_users_sync (priv->accounts_proxy,
2657                                                                     &user_paths,
2658                                                                     NULL, &error);
2659 
2660         if (!could_list) {
2661                 g_debug ("ActUserManager: ListCachedUsers failed: %s", error->message);
2662                 return;
2663         }
2664 
2665         load_user_paths (manager, (const char * const *) user_paths);
2666 
2667         load_included_usernames (manager);
2668 
2669         priv->list_cached_users_done = TRUE;
2670 }
2671 
2672 static gboolean
load_seat_incrementally(ActUserManager * manager)2673 load_seat_incrementally (ActUserManager *manager)
2674 {
2675         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2676 
2677         priv->seat.load_idle_id = 0;
2678 
2679         switch (priv->seat.state) {
2680         case ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_ID:
2681                 get_current_session_id (manager);
2682                 break;
2683         case ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_PROXY:
2684                 get_session_proxy (manager);
2685                 break;
2686         case ACT_USER_MANAGER_SEAT_STATE_GET_ID:
2687                 get_seat_id_for_current_session (manager);
2688                 break;
2689         case ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY:
2690                 get_seat_proxy (manager);
2691                 break;
2692         case ACT_USER_MANAGER_SEAT_STATE_LOADED:
2693                 g_debug ("ActUserManager: Seat loading sequence complete");
2694                 break;
2695         default:
2696                 g_assert_not_reached ();
2697         }
2698 
2699         if (priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_LOADED) {
2700                 load_sessions (manager);
2701         }
2702 
2703         maybe_set_is_loaded (manager);
2704 
2705         return FALSE;
2706 }
2707 
2708 static gboolean
load_idle(ActUserManager * manager)2709 load_idle (ActUserManager *manager)
2710 {
2711         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2712 
2713         priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED + 1;
2714         load_seat_incrementally (manager);
2715         priv->load_id = 0;
2716 
2717         return FALSE;
2718 }
2719 
2720 static void
queue_load_seat(ActUserManager * manager)2721 queue_load_seat (ActUserManager *manager)
2722 {
2723         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2724 
2725         if (priv->load_id > 0) {
2726                 return;
2727         }
2728 
2729         priv->load_id = g_idle_add ((GSourceFunc)load_idle, manager);
2730 }
2731 
2732 static void
act_user_manager_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2733 act_user_manager_get_property (GObject        *object,
2734                                guint           prop_id,
2735                                GValue         *value,
2736                                GParamSpec     *pspec)
2737 {
2738         ActUserManager *manager = ACT_USER_MANAGER (object);
2739         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2740 
2741         switch (prop_id) {
2742         case PROP_IS_LOADED:
2743                 g_value_set_boolean (value, priv->is_loaded);
2744                 break;
2745         case PROP_HAS_MULTIPLE_USERS:
2746                 g_value_set_boolean (value, priv->has_multiple_users);
2747                 break;
2748         case PROP_INCLUDE_USERNAMES_LIST:
2749                 g_value_set_pointer (value, priv->include_usernames);
2750                 break;
2751         case PROP_EXCLUDE_USERNAMES_LIST:
2752                 g_value_set_pointer (value, priv->exclude_usernames);
2753                 break;
2754         default:
2755                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2756                 break;
2757         }
2758 }
2759 
2760 static void
set_include_usernames(ActUserManager * manager,GSList * list)2761 set_include_usernames (ActUserManager *manager,
2762                        GSList         *list)
2763 {
2764         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2765 
2766         if (priv->include_usernames != NULL) {
2767                 g_slist_foreach (priv->include_usernames, (GFunc) g_free, NULL);
2768                 g_slist_free (priv->include_usernames);
2769         }
2770         priv->include_usernames = slist_deep_copy (list);
2771 }
2772 
2773 static void
set_exclude_usernames(ActUserManager * manager,GSList * list)2774 set_exclude_usernames (ActUserManager *manager,
2775                        GSList         *list)
2776 {
2777         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2778 
2779         if (priv->exclude_usernames != NULL) {
2780                 g_slist_foreach (priv->exclude_usernames, (GFunc) g_free, NULL);
2781                 g_slist_free (priv->exclude_usernames);
2782         }
2783         priv->exclude_usernames = slist_deep_copy (list);
2784 }
2785 
2786 static void
act_user_manager_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2787 act_user_manager_set_property (GObject        *object,
2788                                guint           prop_id,
2789                                const GValue   *value,
2790                                GParamSpec     *pspec)
2791 {
2792         ActUserManager *self;
2793 
2794         self = ACT_USER_MANAGER (object);
2795 
2796         switch (prop_id) {
2797         case PROP_INCLUDE_USERNAMES_LIST:
2798                 set_include_usernames (self, g_value_get_pointer (value));
2799                 break;
2800         case PROP_EXCLUDE_USERNAMES_LIST:
2801                 set_exclude_usernames (self, g_value_get_pointer (value));
2802                 break;
2803         case PROP_HAS_MULTIPLE_USERS:
2804                 set_has_multiple_users (self, g_value_get_boolean (value));
2805                 break;
2806         default:
2807                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2808                 break;
2809         }
2810 }
2811 
2812 static void
act_user_manager_class_init(ActUserManagerClass * klass)2813 act_user_manager_class_init (ActUserManagerClass *klass)
2814 {
2815         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
2816 
2817         object_class->finalize = act_user_manager_finalize;
2818         object_class->get_property = act_user_manager_get_property;
2819         object_class->set_property = act_user_manager_set_property;
2820 
2821         g_object_class_install_property (object_class,
2822                                          PROP_IS_LOADED,
2823                                          g_param_spec_boolean ("is-loaded",
2824                                                                "Is loaded",
2825                                                                "Determines whether or not the manager object is loaded and ready to read from.",
2826                                                                FALSE,
2827                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2828         g_object_class_install_property (object_class,
2829                                          PROP_HAS_MULTIPLE_USERS,
2830                                          g_param_spec_boolean ("has-multiple-users",
2831                                                                "Has multiple users",
2832                                                                "Whether more than one normal user is present",
2833                                                                FALSE,
2834                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2835         g_object_class_install_property (object_class,
2836                                          PROP_INCLUDE_USERNAMES_LIST,
2837                                          g_param_spec_pointer ("include-usernames-list",
2838                                                                "Include usernames list",
2839                                                                "Usernames who are specifically included",
2840                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2841 
2842         g_object_class_install_property (object_class,
2843                                          PROP_EXCLUDE_USERNAMES_LIST,
2844                                          g_param_spec_pointer ("exclude-usernames-list",
2845                                                                "Exclude usernames list",
2846                                                                "Usernames who are specifically excluded",
2847                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2848 
2849         /**
2850          * ActUserManager::user-added:
2851          * @gobject: the object which received the signal
2852          * @user: the #ActUser that was added
2853          *
2854          * Emitted when a user is added to the user manager.
2855          */
2856         signals [USER_ADDED] =
2857                 g_signal_new ("user-added",
2858                               G_TYPE_FROM_CLASS (klass),
2859                               G_SIGNAL_RUN_LAST,
2860                               G_STRUCT_OFFSET (ActUserManagerClass, user_added),
2861                               NULL, NULL,
2862                               g_cclosure_marshal_VOID__OBJECT,
2863                               G_TYPE_NONE, 1, ACT_TYPE_USER);
2864         /**
2865          * ActUserManager::user-removed:
2866          * @gobject: the object which received the signal
2867          * @user: the #ActUser that was removed
2868          *
2869          * Emitted when a user is removed from the user manager.
2870          */
2871         signals [USER_REMOVED] =
2872                 g_signal_new ("user-removed",
2873                               G_TYPE_FROM_CLASS (klass),
2874                               G_SIGNAL_RUN_LAST,
2875                               G_STRUCT_OFFSET (ActUserManagerClass, user_removed),
2876                               NULL, NULL,
2877                               g_cclosure_marshal_VOID__OBJECT,
2878                               G_TYPE_NONE, 1, ACT_TYPE_USER);
2879         /**
2880          * ActUserManager::user-is-logged-in-changed:
2881          * @gobject: the object which received the signal
2882          * @user: the #ActUser that changed login status
2883          *
2884          * One of the users has logged in or out.
2885          */
2886         signals [USER_IS_LOGGED_IN_CHANGED] =
2887                 g_signal_new ("user-is-logged-in-changed",
2888                               G_TYPE_FROM_CLASS (klass),
2889                               G_SIGNAL_RUN_LAST,
2890                               G_STRUCT_OFFSET (ActUserManagerClass, user_is_logged_in_changed),
2891                               NULL, NULL,
2892                               g_cclosure_marshal_VOID__OBJECT,
2893                               G_TYPE_NONE, 1, ACT_TYPE_USER);
2894         /**
2895          * ActUserManager::user-changed:
2896          * @gobject: the object which received the signal
2897          * @user: the #ActUser that changed
2898          *
2899          * One of the users has changed
2900          */
2901         signals [USER_CHANGED] =
2902                 g_signal_new ("user-changed",
2903                               G_TYPE_FROM_CLASS (klass),
2904                               G_SIGNAL_RUN_LAST,
2905                               G_STRUCT_OFFSET (ActUserManagerClass, user_changed),
2906                               NULL, NULL,
2907                               g_cclosure_marshal_VOID__OBJECT,
2908                               G_TYPE_NONE, 1, ACT_TYPE_USER);
2909 }
2910 
2911 /**
2912  * act_user_manager_queue_load:
2913  * @manager: a #ActUserManager
2914  *
2915  * Queue loading users into user manager. This must be called, and the
2916  * #ActUserManager:is-loaded property must be %TRUE before calling
2917  * act_user_manager_list_users()
2918  */
2919 static void
act_user_manager_queue_load(ActUserManager * manager)2920 act_user_manager_queue_load (ActUserManager *manager)
2921 {
2922         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2923 
2924         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
2925 
2926         if (!priv->is_loaded) {
2927                 queue_load_seat (manager);
2928         }
2929 }
2930 
2931 static gboolean
ensure_accounts_proxy(ActUserManager * manager)2932 ensure_accounts_proxy (ActUserManager *manager)
2933 {
2934         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2935         g_autoptr(GError) error = NULL;
2936 
2937         if (priv->accounts_proxy != NULL) {
2938                 return TRUE;
2939         }
2940 
2941         priv->accounts_proxy = accounts_accounts_proxy_new_sync (priv->connection,
2942                                                                  G_DBUS_PROXY_FLAGS_NONE,
2943                                                                  ACCOUNTS_NAME,
2944                                                                  ACCOUNTS_PATH,
2945                                                                  NULL,
2946                                                                  &error);
2947         if (error != NULL) {
2948                 g_debug ("ActUserManager: getting account proxy failed: %s", error->message);
2949                 return FALSE;
2950         }
2951 
2952         g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->accounts_proxy), G_MAXINT);
2953 
2954         g_object_bind_property (G_OBJECT (priv->accounts_proxy),
2955                                 "has-multiple-users",
2956                                 G_OBJECT (manager),
2957                                 "has-multiple-users",
2958                                 G_BINDING_SYNC_CREATE);
2959 
2960         g_signal_connect (priv->accounts_proxy,
2961                           "user-added",
2962                           G_CALLBACK (on_new_user_in_accounts_service),
2963                           manager);
2964         g_signal_connect (priv->accounts_proxy,
2965                           "user-deleted",
2966                           G_CALLBACK (on_user_removed_in_accounts_service),
2967                           manager);
2968 
2969         return TRUE;
2970 }
2971 
2972 static void
act_user_manager_init(ActUserManager * manager)2973 act_user_manager_init (ActUserManager *manager)
2974 {
2975         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
2976         g_autoptr(GError) error = NULL;
2977 
2978         act_user_manager_error_quark (); /* register dbus errors */
2979 
2980         /* sessions */
2981         priv->sessions = g_hash_table_new_full (g_str_hash,
2982                                                 g_str_equal,
2983                                                 g_free,
2984                                                 g_object_unref);
2985 
2986         /* users */
2987         priv->normal_users_by_name = g_hash_table_new_full (g_str_hash,
2988                                                             g_str_equal,
2989                                                             g_free,
2990                                                             g_object_unref);
2991         priv->system_users_by_name = g_hash_table_new_full (g_str_hash,
2992                                                             g_str_equal,
2993                                                             g_free,
2994                                                             g_object_unref);
2995         priv->users_by_object_path = g_hash_table_new_full (g_str_hash,
2996                                                             g_str_equal,
2997                                                             NULL,
2998                                                             g_object_unref);
2999 
3000         priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
3001         if (priv->connection == NULL) {
3002                 if (error != NULL) {
3003                         g_warning ("Failed to connect to the D-Bus daemon: %s", error->message);
3004                 } else {
3005                         g_warning ("Failed to connect to the D-Bus daemon");
3006                 }
3007                 return;
3008         }
3009 
3010         ensure_accounts_proxy (manager);
3011 
3012         priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED;
3013 }
3014 
3015 static void
act_user_manager_finalize(GObject * object)3016 act_user_manager_finalize (GObject *object)
3017 {
3018         ActUserManager *manager = ACT_USER_MANAGER (object);
3019         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3020         GSList         *node;
3021 
3022         g_debug ("ActUserManager: finalizing user manager");
3023 
3024         g_slist_foreach (priv->new_sessions,
3025                          (GFunc) unload_new_session, NULL);
3026         g_slist_free (priv->new_sessions);
3027 
3028         g_slist_foreach (priv->fetch_user_requests,
3029                          (GFunc) free_fetch_user_request, NULL);
3030         g_slist_free (priv->fetch_user_requests);
3031 
3032         g_slist_free (priv->new_users_inhibiting_load);
3033 
3034         node = priv->new_users;
3035         while (node != NULL) {
3036                 ActUser *user;
3037                 GSList  *next_node;
3038 
3039                 user = ACT_USER (node->data);
3040                 next_node = node->next;
3041 
3042                 g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
3043                 g_object_unref (user);
3044                 priv->new_users = g_slist_delete_link (priv->new_users, node);
3045                 node = next_node;
3046         }
3047 
3048         unload_seat (manager);
3049 
3050         if (priv->exclude_usernames != NULL) {
3051                 g_slist_foreach (priv->exclude_usernames, (GFunc) g_free, NULL);
3052                 g_slist_free (priv->exclude_usernames);
3053         }
3054 
3055         if (priv->include_usernames != NULL) {
3056                 g_slist_foreach (priv->include_usernames, (GFunc) g_free, NULL);
3057                 g_slist_free (priv->include_usernames);
3058         }
3059 
3060         if (priv->seat.seat_proxy != NULL) {
3061                 g_object_unref (priv->seat.seat_proxy);
3062         }
3063 
3064         if (priv->seat.session_proxy != NULL) {
3065                 g_object_unref (priv->seat.session_proxy);
3066         }
3067 
3068         if (priv->seat.load_idle_id != 0) {
3069                 g_source_remove (priv->seat.load_idle_id);
3070         }
3071 
3072 #ifdef WITH_SYSTEMD
3073         if (priv->seat.session_monitor != NULL) {
3074                 sd_login_monitor_unref (priv->seat.session_monitor);
3075         }
3076 
3077         if (priv->seat.session_monitor_stream != NULL) {
3078                 g_object_unref (priv->seat.session_monitor_stream);
3079         }
3080 
3081         if (priv->seat.session_monitor_source_id != 0) {
3082                 g_source_remove (priv->seat.session_monitor_source_id);
3083         }
3084 #endif
3085 
3086         if (priv->accounts_proxy != NULL) {
3087                 g_object_unref (priv->accounts_proxy);
3088         }
3089 
3090         if (priv->load_id > 0) {
3091                 g_source_remove (priv->load_id);
3092                 priv->load_id = 0;
3093         }
3094 
3095         g_hash_table_destroy (priv->sessions);
3096 
3097         g_hash_table_destroy (priv->normal_users_by_name);
3098         g_hash_table_destroy (priv->system_users_by_name);
3099         g_hash_table_destroy (priv->users_by_object_path);
3100 
3101         G_OBJECT_CLASS (act_user_manager_parent_class)->finalize (object);
3102 }
3103 
3104 /**
3105  * act_user_manager_get_default:
3106  *
3107  * Returns the user manager singleton instance.  Calling this function will
3108  * automatically being loading the user list if it isn't loaded already.
3109  * The #ActUserManager:is-loaded property will be set to %TRUE when the users
3110  * are finished loading and then act_user_manager_list_users() can be called.
3111  *
3112  * Returns: (transfer none): user manager object
3113  */
3114 ActUserManager *
act_user_manager_get_default(void)3115 act_user_manager_get_default (void)
3116 {
3117         if (user_manager_object == NULL) {
3118                 user_manager_object = g_object_new (ACT_TYPE_USER_MANAGER, NULL);
3119                 g_object_add_weak_pointer (user_manager_object,
3120                                            (gpointer *) &user_manager_object);
3121                 act_user_manager_queue_load (user_manager_object);
3122         }
3123 
3124         return ACT_USER_MANAGER (user_manager_object);
3125 }
3126 
3127 /**
3128  * act_user_manager_no_service:
3129  * @manager: a #ActUserManager
3130  *
3131  * Check whether or not the accounts service is running.
3132  *
3133  * Returns: whether or not accounts service is running
3134  */
3135 gboolean
act_user_manager_no_service(ActUserManager * manager)3136 act_user_manager_no_service (ActUserManager *manager)
3137 {
3138         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3139         return priv->accounts_proxy == NULL;
3140 }
3141 
3142 /**
3143  * act_user_manager_create_user:
3144  * @manager: a #ActUserManager
3145  * @username: a unix user name
3146  * @fullname: a unix GECOS value
3147  * @accounttype: a #ActUserAccountType
3148  * @error: a #GError
3149  *
3150  * Creates a user account on the system.
3151  *
3152  * Returns: (transfer full): user object
3153  */
3154 ActUser *
act_user_manager_create_user(ActUserManager * manager,const char * username,const char * fullname,ActUserAccountType accounttype,GError ** error)3155 act_user_manager_create_user (ActUserManager      *manager,
3156                               const char          *username,
3157                               const char          *fullname,
3158                               ActUserAccountType   accounttype,
3159                               GError             **error)
3160 {
3161         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3162         GError *local_error = NULL;
3163         gboolean res;
3164         g_autofree gchar *path = NULL;
3165         ActUser *user;
3166 
3167         g_debug ("ActUserManager: Creating user '%s', '%s', %d",
3168                  username, fullname, accounttype);
3169 
3170         g_assert (priv->accounts_proxy != NULL);
3171 
3172         res = accounts_accounts_call_create_user_sync (priv->accounts_proxy,
3173                                                        username,
3174                                                        fullname,
3175                                                        accounttype,
3176                                                        &path,
3177                                                        NULL,
3178                                                        &local_error);
3179         if (!res) {
3180                 g_propagate_error (error, local_error);
3181                 return NULL;
3182         }
3183 
3184         user = add_new_user_for_object_path (path, manager);
3185 
3186         return user;
3187 }
3188 
3189 static void
act_user_manager_async_complete_handler(GObject * source,GAsyncResult * result,gpointer user_data)3190 act_user_manager_async_complete_handler (GObject      *source,
3191                                          GAsyncResult *result,
3192                                          gpointer      user_data)
3193 {
3194         GTask *task = user_data;
3195 
3196         g_task_return_pointer (task, g_object_ref (result), g_object_unref);
3197         g_object_unref (task);
3198 }
3199 
3200 /**
3201  * act_user_manager_create_user_async:
3202  * @manager: a #ActUserManager
3203  * @username: a unix user name
3204  * @fullname: a unix GECOS value
3205  * @accounttype: a #ActUserAccountType
3206  * @cancellable: (allow-none): optional #GCancellable object,
3207  *     %NULL to ignore
3208  * @callback: (scope async): a #GAsyncReadyCallback to call
3209  *     when the request is satisfied
3210  * @user_data: (closure): the data to pass to @callback
3211  *
3212  * Asynchronously creates a user account on the system.
3213  *
3214  * For more details, see act_user_manager_create_user(), which
3215  * is the synchronous version of this call.
3216  *
3217  * Since: 0.6.27
3218  */
3219 void
act_user_manager_create_user_async(ActUserManager * manager,const char * username,const char * fullname,ActUserAccountType accounttype,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3220 act_user_manager_create_user_async (ActUserManager      *manager,
3221                                     const char          *username,
3222                                     const char          *fullname,
3223                                     ActUserAccountType   accounttype,
3224                                     GCancellable        *cancellable,
3225                                     GAsyncReadyCallback  callback,
3226                                     gpointer             user_data)
3227 {
3228         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3229         GTask *task;
3230 
3231         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
3232         g_return_if_fail (priv->accounts_proxy != NULL);
3233 
3234         g_debug ("ActUserManager: Creating user (async) '%s', '%s', %d",
3235                  username, fullname, accounttype);
3236 
3237         g_assert (priv->accounts_proxy != NULL);
3238 
3239         task = g_task_new (G_OBJECT (manager),
3240                            cancellable,
3241                            callback, user_data);
3242 
3243         accounts_accounts_call_create_user (priv->accounts_proxy,
3244                                             username,
3245                                             fullname,
3246                                             accounttype,
3247                                             cancellable,
3248                                             act_user_manager_async_complete_handler, task);
3249 }
3250 
3251 /**
3252  * act_user_manager_create_user_finish:
3253  * @manager: a #ActUserManager
3254  * @result: a #GAsyncResult
3255  * @error: a #GError
3256  *
3257  * Finishes an asynchronous user creation.
3258  *
3259  * See act_user_manager_create_user_async().
3260  *
3261  * Returns: (transfer full): user object
3262  *
3263  * Since: 0.6.27
3264  */
3265 ActUser *
act_user_manager_create_user_finish(ActUserManager * manager,GAsyncResult * result,GError ** error)3266 act_user_manager_create_user_finish (ActUserManager  *manager,
3267                                      GAsyncResult    *result,
3268                                      GError         **error)
3269 {
3270         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3271         GAsyncResult *inner_result;
3272         ActUser *user = NULL;
3273         g_autofree gchar *path = NULL;
3274         GError *remote_error = NULL;
3275 
3276         inner_result = g_task_propagate_pointer (G_TASK (result), error);
3277         if (inner_result == NULL) {
3278                 return FALSE;
3279         }
3280 
3281         if (accounts_accounts_call_create_user_finish (priv->accounts_proxy,
3282                                                        &path, inner_result, &remote_error)) {
3283                 user = add_new_user_for_object_path (path, manager);
3284         }
3285 
3286         if (remote_error) {
3287                 g_dbus_error_strip_remote_error (remote_error);
3288                 g_propagate_error (error, remote_error);
3289         }
3290 
3291         return user;
3292 }
3293 
3294 /**
3295  * act_user_manager_cache_user:
3296  * @manager: a #ActUserManager
3297  * @username: a user name
3298  * @error: a #GError
3299  *
3300  * Caches a user account so it shows up via act_user_manager_list_users().
3301  *
3302  * Returns: (transfer full): user object
3303  */
3304 ActUser *
act_user_manager_cache_user(ActUserManager * manager,const char * username,GError ** error)3305 act_user_manager_cache_user (ActUserManager     *manager,
3306                              const char         *username,
3307                              GError            **error)
3308 {
3309         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3310         GError *local_error = NULL;
3311         gboolean res;
3312         g_autofree gchar *path = NULL;
3313 
3314         g_debug ("ActUserManager: Caching user '%s'",
3315                  username);
3316 
3317         g_assert (priv->accounts_proxy != NULL);
3318 
3319         res = accounts_accounts_call_cache_user_sync (priv->accounts_proxy,
3320                                                       username,
3321                                                       &path,
3322                                                       NULL,
3323                                                       &local_error);
3324         if (!res) {
3325                 g_propagate_error (error, local_error);
3326                 return NULL;
3327         }
3328 
3329         return add_new_user_for_object_path (path, manager);
3330 }
3331 
3332 
3333 /**
3334  * act_user_manager_cache_user_async:
3335  * @manager: a #ActUserManager
3336  * @username: a unix user name
3337  * @cancellable: (allow-none): optional #GCancellable object,
3338  *     %NULL to ignore
3339  * @callback: (scope async): a #GAsyncReadyCallback to call
3340  *     when the request is satisfied
3341  * @user_data: (closure): the data to pass to @callback
3342  *
3343  * Asynchronously caches a user account so it shows up via
3344  * act_user_manager_list_users().
3345  *
3346  * For more details, see act_user_manager_cache_user(), which
3347  * is the synchronous version of this call.
3348  *
3349  * Since: 0.6.27
3350  */
3351 void
act_user_manager_cache_user_async(ActUserManager * manager,const char * username,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3352 act_user_manager_cache_user_async (ActUserManager      *manager,
3353                                    const char          *username,
3354                                    GCancellable        *cancellable,
3355                                    GAsyncReadyCallback  callback,
3356                                    gpointer             user_data)
3357 {
3358         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3359         GTask *task;
3360 
3361         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
3362         g_return_if_fail (priv->accounts_proxy != NULL);
3363 
3364         g_debug ("ActUserManager: Caching user (async) '%s'", username);
3365 
3366         task = g_task_new (G_OBJECT (manager),
3367                            cancellable,
3368                            callback, user_data);
3369 
3370         accounts_accounts_call_cache_user (priv->accounts_proxy,
3371                                            username,
3372                                            cancellable,
3373                                            act_user_manager_async_complete_handler, task);
3374 }
3375 
3376 /**
3377  * act_user_manager_cache_user_finish:
3378  * @manager: a #ActUserManager
3379  * @result: a #GAsyncResult
3380  * @error: a #GError
3381  *
3382  * Finishes an asynchronous user caching.
3383  *
3384  * See act_user_manager_cache_user_async().
3385  *
3386  * Returns: (transfer full): user object
3387  *
3388  * Since: 0.6.27
3389  */
3390 ActUser *
act_user_manager_cache_user_finish(ActUserManager * manager,GAsyncResult * result,GError ** error)3391 act_user_manager_cache_user_finish (ActUserManager  *manager,
3392                                     GAsyncResult    *result,
3393                                     GError         **error)
3394 {
3395         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3396         GAsyncResult *inner_result;
3397         ActUser *user = NULL;
3398         g_autofree gchar *path = NULL;
3399         GError *remote_error = NULL;
3400 
3401         inner_result = g_task_propagate_pointer (G_TASK (result), error);
3402         if (inner_result == NULL) {
3403                 return FALSE;
3404         }
3405 
3406         if (accounts_accounts_call_cache_user_finish (priv->accounts_proxy,
3407                                                       &path, inner_result, &remote_error)) {
3408                 user = add_new_user_for_object_path (path, manager);
3409         }
3410 
3411         if (remote_error) {
3412                 g_dbus_error_strip_remote_error (remote_error);
3413                 g_propagate_error (error, remote_error);
3414         }
3415 
3416         return user;
3417 }
3418 
3419 /**
3420  * act_user_manager_uncache_user:
3421  * @manager: a #ActUserManager
3422  * @username: a user name
3423  * @error: a #GError
3424  *
3425  * Releases all metadata about a user account, including icon,
3426  * language and session. If the user account is from a remote
3427  * server and the user has never logged in before, then that
3428  * account will no longer show up in ListCachedUsers() output.
3429  *
3430  * Returns: %TRUE if successful, otherwise %FALSE
3431  */
3432 gboolean
act_user_manager_uncache_user(ActUserManager * manager,const char * username,GError ** error)3433 act_user_manager_uncache_user (ActUserManager     *manager,
3434                                const char         *username,
3435                                GError            **error)
3436 {
3437         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3438         GError *local_error = NULL;
3439         gboolean res;
3440 
3441         g_debug ("ActUserManager: Uncaching user '%s'",
3442                  username);
3443 
3444         g_assert (priv->accounts_proxy != NULL);
3445 
3446         res = accounts_accounts_call_uncache_user_sync (priv->accounts_proxy,
3447                                                         username,
3448                                                         NULL,
3449                                                         &local_error);
3450         if (!res) {
3451                 g_propagate_error (error, local_error);
3452                 return FALSE;
3453         }
3454 
3455         return TRUE;
3456 }
3457 
3458 /*
3459  * act_user_manager_uncache_user_async:
3460  * @manager: a #ActUserManager
3461  * @username: a unix user name
3462  * @cancellable: (allow-none): optional #GCancellable object,
3463  *     %NULL to ignore
3464  * @callback: (scope async): a #GAsyncReadyCallback to call
3465  *     when the request is satisfied
3466  * @user_data: (closure): the data to pass to @callback
3467  *
3468  * Asynchronously uncaches a user account.
3469  *
3470  * For more details, see act_user_manager_uncache_user(), which
3471  * is the synchronous version of this call.
3472  *
3473  * Since: 0.6.39
3474  */
3475 void
act_user_manager_uncache_user_async(ActUserManager * manager,const char * username,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3476 act_user_manager_uncache_user_async (ActUserManager      *manager,
3477                                      const char          *username,
3478                                      GCancellable        *cancellable,
3479                                      GAsyncReadyCallback  callback,
3480                                      gpointer             user_data)
3481 {
3482         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3483         GTask *task;
3484 
3485         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
3486         g_return_if_fail (username != NULL);
3487         g_return_if_fail (priv->accounts_proxy != NULL);
3488 
3489         g_debug ("ActUserManager: Uncaching user (async) '%s'", username);
3490 
3491         task = g_task_new (G_OBJECT (manager),
3492                            cancellable,
3493                            callback, user_data);
3494 
3495         accounts_accounts_call_uncache_user (priv->accounts_proxy,
3496                                              username,
3497                                              cancellable,
3498                                              act_user_manager_async_complete_handler, task);
3499 }
3500 
3501 /**
3502  * act_user_manager_uncache_user_finish:
3503  * @manager: a #ActUserManager
3504  * @result: a #GAsyncResult
3505  * @error: a #GError
3506  *
3507  * Finishes an asynchronous user uncaching.
3508  *
3509  * See act_user_manager_uncache_user_async().
3510  *
3511  * Returns: %TRUE if the user account was successfully uncached
3512  *
3513  * Since: 0.6.39
3514  */
3515 gboolean
act_user_manager_uncache_user_finish(ActUserManager * manager,GAsyncResult * result,GError ** error)3516 act_user_manager_uncache_user_finish (ActUserManager  *manager,
3517                                       GAsyncResult    *result,
3518                                       GError         **error)
3519 {
3520         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3521         GAsyncResult *inner_result;
3522         gboolean success;
3523         GError *remote_error = NULL;
3524 
3525         inner_result = g_task_propagate_pointer (G_TASK (result), error);
3526         if (inner_result == NULL) {
3527                 return FALSE;
3528         }
3529 
3530         success = accounts_accounts_call_uncache_user_finish (priv->accounts_proxy,
3531                                                               inner_result, &remote_error);
3532 
3533         if (remote_error) {
3534                 g_dbus_error_strip_remote_error (remote_error);
3535                 g_propagate_error (error, remote_error);
3536         }
3537 
3538         return success;
3539 }
3540 
3541 /**
3542  * act_user_manager_delete_user:
3543  * @manager: a #ActUserManager
3544  * @user: an #ActUser object
3545  * @remove_files: %TRUE to delete the users home directory
3546  * @error: a #GError
3547  *
3548  * Deletes a user account on the system.
3549  *
3550  * Returns: %TRUE if the user account was successfully deleted
3551  */
3552 gboolean
act_user_manager_delete_user(ActUserManager * manager,ActUser * user,gboolean remove_files,GError ** error)3553 act_user_manager_delete_user (ActUserManager  *manager,
3554                               ActUser         *user,
3555                               gboolean         remove_files,
3556                               GError         **error)
3557 {
3558         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3559         GError *local_error = NULL;
3560 
3561         g_debug ("ActUserManager: Deleting user '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user));
3562 
3563         g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), FALSE);
3564         g_return_val_if_fail (ACT_IS_USER (user), FALSE);
3565         g_return_val_if_fail (priv->accounts_proxy != NULL, FALSE);
3566 
3567         if (!accounts_accounts_call_delete_user_sync (priv->accounts_proxy,
3568                                                       act_user_get_uid (user),
3569                                                       remove_files,
3570                                                       NULL,
3571                                                       &local_error)) {
3572                 g_propagate_error (error, local_error);
3573                 return FALSE;
3574         }
3575 
3576         return TRUE;
3577 }
3578 
3579 /**
3580  * act_user_manager_delete_user_async:
3581  * @manager: a #ActUserManager
3582  * @user: a #ActUser object
3583  * @remove_files: %TRUE to delete the users home directory
3584  * @cancellable: (allow-none): optional #GCancellable object,
3585  *     %NULL to ignore
3586  * @callback: (scope async): a #GAsyncReadyCallback to call
3587  *     when the request is satisfied
3588  * @user_data: (closure): the data to pass to @callback
3589  *
3590  * Asynchronously deletes a user account from the system.
3591  *
3592  * For more details, see act_user_manager_delete_user(), which
3593  * is the synchronous version of this call.
3594  *
3595  * Since: 0.6.27
3596  */
3597 void
act_user_manager_delete_user_async(ActUserManager * manager,ActUser * user,gboolean remove_files,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3598 act_user_manager_delete_user_async (ActUserManager      *manager,
3599                                     ActUser             *user,
3600                                     gboolean             remove_files,
3601                                     GCancellable        *cancellable,
3602                                     GAsyncReadyCallback  callback,
3603                                     gpointer             user_data)
3604 {
3605         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3606         GTask *task;
3607 
3608         g_return_if_fail (ACT_IS_USER_MANAGER (manager));
3609         g_return_if_fail (ACT_IS_USER (user));
3610         g_return_if_fail (priv->accounts_proxy != NULL);
3611 
3612         task = g_task_new (G_OBJECT (manager),
3613                            cancellable,
3614                            callback, user_data);
3615 
3616         g_debug ("ActUserManager: Deleting (async) user '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user));
3617 
3618         accounts_accounts_call_delete_user (priv->accounts_proxy,
3619                                             act_user_get_uid (user), remove_files,
3620                                             cancellable,
3621                                             act_user_manager_async_complete_handler, task);
3622 }
3623 
3624 /**
3625  * act_user_manager_delete_user_finish:
3626  * @manager: a #ActUserManager
3627  * @result: a #GAsyncResult
3628  * @error: a #GError
3629  *
3630  * Finishes an asynchronous user account deletion.
3631  *
3632  * See act_user_manager_delete_user_async().
3633  *
3634  * Returns: %TRUE if the user account was successfully deleted
3635  *
3636  * Since: 0.6.27
3637  */
3638 gboolean
act_user_manager_delete_user_finish(ActUserManager * manager,GAsyncResult * result,GError ** error)3639 act_user_manager_delete_user_finish (ActUserManager  *manager,
3640                                      GAsyncResult    *result,
3641                                      GError         **error)
3642 {
3643         ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager);
3644         GAsyncResult *inner_result;
3645         gboolean success;
3646         GError *remote_error = NULL;
3647 
3648         inner_result = g_task_propagate_pointer (G_TASK (result), error);
3649         if (inner_result == NULL) {
3650                 return FALSE;
3651         }
3652 
3653         success = accounts_accounts_call_delete_user_finish (priv->accounts_proxy,
3654                                                              inner_result, &remote_error);
3655         if (remote_error) {
3656                 g_dbus_error_strip_remote_error (remote_error);
3657                 g_propagate_error (error, remote_error);
3658         }
3659 
3660         return success;
3661 }
3662