summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/org.freedesktop.Accounts.User.xml10
-rw-r--r--src/daemon.c30
-rw-r--r--src/libaccountsservice/act-user.c36
-rw-r--r--src/libaccountsservice/act-user.h1
-rw-r--r--src/user.c15
5 files changed, 82 insertions, 10 deletions
diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml
index deab745..11884d6 100644
--- a/data/org.freedesktop.Accounts.User.xml
+++ b/data/org.freedesktop.Accounts.User.xml
@@ -653,6 +653,16 @@
</doc:doc>
</property>
+ <property name="LoginTime" type="x" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The last login time.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
<property name="IconFile" type="s" access="read">
<doc:doc>
<doc:description>
diff --git a/src/daemon.c b/src/daemon.c
index 84474b6..8000192 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -205,6 +205,12 @@ daemon_local_user_is_excluded (Daemon *daemon, const gchar *username, const gcha
}
#ifdef HAVE_UTMPX_H
+
+typedef struct {
+ int frequency;
+ gint64 time;
+} UserAccounting;
+
static struct passwd *
entry_generator_wtmp (GHashTable *users,
gpointer *state)
@@ -214,6 +220,7 @@ entry_generator_wtmp (GHashTable *users,
GHashTableIter iter;
gpointer key, value;
struct passwd *pwent;
+ User *user;
if (*state == NULL) {
/* First iteration */
@@ -231,6 +238,9 @@ entry_generator_wtmp (GHashTable *users,
/* Every iteration */
login_frequency_hash = *state;
while ((wtmp_entry = getutxent ())) {
+
+ UserAccounting *accounting;
+
if (wtmp_entry->ut_type != USER_PROCESS) {
continue;
}
@@ -247,17 +257,16 @@ entry_generator_wtmp (GHashTable *users,
if (!g_hash_table_lookup_extended (login_frequency_hash,
wtmp_entry->ut_user,
&key, &value)) {
+ accounting = g_new (UserAccounting, 1);
+ accounting->frequency = 1;
+ accounting->time = wtmp_entry->ut_tv.tv_sec;
g_hash_table_insert (login_frequency_hash,
g_strdup (wtmp_entry->ut_user),
- GUINT_TO_POINTER (1));
+ accounting);
} else {
- guint frequency;
-
- frequency = GPOINTER_TO_UINT (value) + 1;
-
- g_hash_table_insert (login_frequency_hash,
- key,
- GUINT_TO_POINTER (frequency));
+ accounting = value;
+ accounting->frequency++;
+ accounting->time = wtmp_entry->ut_tv.tv_sec;
}
return pwent;
@@ -269,14 +278,15 @@ entry_generator_wtmp (GHashTable *users,
g_hash_table_iter_init (&iter, login_frequency_hash);
while (g_hash_table_iter_next (&iter, &key, &value)) {
User *user;
- guint64 frequency = (guint64) GPOINTER_TO_UINT (value);
+ UserAccounting *accounting = (UserAccounting *) value;
user = g_hash_table_lookup (users, key);
if (user == NULL) {
continue;
}
- g_object_set (user, "login-frequency", frequency, NULL);
+ g_object_set (user, "login-frequency", accounting->frequency, NULL);
+ g_object_set (user, "login-time", accounting->time, NULL);
}
g_hash_table_foreach (login_frequency_hash, (GHFunc) g_free, NULL);
diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c
index 13d82e7..33d15a8 100644
--- a/src/libaccountsservice/act-user.c
+++ b/src/libaccountsservice/act-user.c
@@ -57,6 +57,7 @@ enum {
PROP_SYSTEM_ACCOUNT,
PROP_LOCAL_ACCOUNT,
PROP_LOGIN_FREQUENCY,
+ PROP_LOGIN_TIME,
PROP_ICON_FILE,
PROP_LANGUAGE,
PROP_X_SESSION,
@@ -91,6 +92,7 @@ struct _ActUser {
char *x_session;
GList *sessions;
int login_frequency;
+ gint64 login_time;
ActUserAccountType account_type;
ActUserPasswordMode password_mode;
@@ -206,6 +208,9 @@ act_user_get_property (GObject *object,
case PROP_LOGIN_FREQUENCY:
g_value_set_int (value, user->login_frequency);
break;
+ case PROP_LOGIN_TIME:
+ g_value_set_int64 (value, user->login_time);
+ break;
case PROP_SHELL:
g_value_set_string (value, user->shell);
break;
@@ -343,6 +348,15 @@ act_user_class_init (ActUserClass *class)
0,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
+ PROP_LOGIN_TIME,
+ g_param_spec_int64 ("login-time",
+ "Login time",
+ "The last login time for this user.",
+ 0,
+ G_MAXINT64,
+ 0,
+ G_PARAM_READABLE));
+ g_object_class_install_property (gobject_class,
PROP_ICON_FILE,
g_param_spec_string ("icon-file",
"Icon File",
@@ -676,6 +690,21 @@ act_user_get_login_frequency (ActUser *user)
return user->login_frequency;
}
+/**
+ * act_user_get_login_time:
+ * @user: a #ActUser
+ *
+ * Returns the last login time for @user.
+ *
+ * Returns: (transfer none): the login time
+ */
+gint64
+act_user_get_login_time (ActUser *user) {
+ g_return_val_if_fail (ACT_IS_USER (user), 0);
+
+ return user->login_time;
+}
+
int
act_user_collate (ActUser *user1,
ActUser *user2)
@@ -1036,6 +1065,13 @@ collect_props (const gchar *key,
user->login_frequency = new_login_frequency;
g_object_notify (G_OBJECT (user), "login-frequency");
}
+ } else if (strcmp (key, "LoginTime") == 0) {
+ gint64 new_login_time = value;
+
+ if (user->login_time != new_login_time) {
+ user->login_time = new_login_time;
+ g_object_notify (G_OBJECT (user), "login-time");
+ }
} else if (strcmp (key, "IconFile") == 0) {
const char *new_icon_file;
diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h
index c01c1e9..70a97c1 100644
--- a/src/libaccountsservice/act-user.h
+++ b/src/libaccountsservice/act-user.h
@@ -66,6 +66,7 @@ const char *act_user_get_location (ActUser *user);
guint act_user_get_num_sessions (ActUser *user);
gboolean act_user_is_logged_in (ActUser *user);
int act_user_get_login_frequency (ActUser *user);
+gint64 act_user_get_login_time (ActUser *user);
gboolean act_user_get_locked (ActUser *user);
gboolean act_user_get_automatic_login (ActUser *user);
gboolean act_user_is_system_account (ActUser *user);
diff --git a/src/user.c b/src/user.c
index ff84c6d..f9e09a6 100644
--- a/src/user.c
+++ b/src/user.c
@@ -59,6 +59,7 @@ enum {
PROP_X_SESSION,
PROP_LOCATION,
PROP_LOGIN_FREQUENCY,
+ PROP_LOGIN_TIME,
PROP_ICON_FILE,
PROP_LOCKED,
PROP_PASSWORD_MODE,
@@ -90,6 +91,7 @@ struct User {
gchar *x_session;
gchar *location;
guint64 login_frequency;
+ gint64 login_time;
gchar *icon_file;
gchar *default_icon_file;
gboolean locked;
@@ -1683,6 +1685,12 @@ user_real_get_login_frequency (AccountsUser *user)
return USER (user)->login_frequency;
}
+static gint64
+user_real_get_login_time (AccountsUser *user)
+{
+ return USER (user)->login_time;
+}
+
static const gchar *
user_real_get_icon_file (AccountsUser *user)
{
@@ -1770,6 +1778,9 @@ user_set_property (GObject *object,
case PROP_LOGIN_FREQUENCY:
user->login_frequency = g_value_get_uint64 (value);
break;
+ case PROP_LOGIN_TIME:
+ user->login_time = g_value_get_int64 (value);
+ break;
case PROP_AUTOMATIC_LOGIN:
user->automatic_login = g_value_get_boolean (value);
break;
@@ -1840,6 +1851,9 @@ user_get_property (GObject *object,
case PROP_LOGIN_FREQUENCY:
g_value_set_uint64 (value, user->login_frequency);
break;
+ case PROP_LOGIN_TIME:
+ g_value_set_int64 (value, user->login_time);
+ break;
case PROP_LOCKED:
g_value_set_boolean (value, user->locked);
break;
@@ -1900,6 +1914,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface)
iface->get_xsession = user_real_get_xsession;
iface->get_location = user_real_get_location;
iface->get_login_frequency = user_real_get_login_frequency;
+ iface->get_login_time = user_real_get_login_time;
iface->get_icon_file = user_real_get_icon_file;
iface->get_locked = user_real_get_locked;
iface->get_password_mode = user_real_get_password_mode;