163 lines
6.1 KiB
Text
163 lines
6.1 KiB
Text
Index: src/wtmp-helper.c
|
|
--- src/wtmp-helper.c.orig
|
|
+++ src/wtmp-helper.c
|
|
@@ -25,10 +25,6 @@
|
|
#include "wtmp-helper.h"
|
|
#include "user.h"
|
|
|
|
-#ifdef HAVE_UTMPX_H
|
|
-
|
|
-#include <utmpx.h>
|
|
-
|
|
typedef struct
|
|
{
|
|
guint64 frequency;
|
|
@@ -50,6 +46,10 @@ user_previous_login_free (UserPreviousLogin *previous_
|
|
g_free (previous_login);
|
|
}
|
|
|
|
+#ifdef HAVE_UTMPX_H
|
|
+
|
|
+#include <utmpx.h>
|
|
+
|
|
static gboolean
|
|
wtmp_helper_start (void)
|
|
{
|
|
@@ -215,10 +215,136 @@ wtmp_helper_get_path_for_monitor (void)
|
|
|
|
#else /* HAVE_UTMPX_H */
|
|
|
|
+#include <stdio.h>
|
|
+#include <utmp.h>
|
|
+
|
|
+void
|
|
+wtmp_helper_update_login_frequencies (GHashTable *users)
|
|
+{
|
|
+ GHashTable *login_hash, *logout_hash;
|
|
+ struct utmp wtmp_entry;
|
|
+ GHashTableIter iter;
|
|
+ gpointer key, value;
|
|
+ User *user;
|
|
+ GVariantBuilder *builder, *builder2;
|
|
+ GList *l;
|
|
+ FILE *fp;
|
|
+
|
|
+ login_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
|
+ logout_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
+
|
|
+ fp = fopen(_PATH_WTMP, "r");
|
|
+ if (fp == NULL)
|
|
+ return;
|
|
+
|
|
+ while (fread(&wtmp_entry, sizeof(wtmp_entry), 1, fp) == 1) {
|
|
+ UserAccounting *accounting;
|
|
+ UserPreviousLogin *previous_login;
|
|
+ gboolean shutdown_or_reboot = FALSE;
|
|
+
|
|
+ if (g_str_equal (wtmp_entry.ut_line, "~")) {
|
|
+ if (g_str_equal (wtmp_entry.ut_name, "shutdown") ||
|
|
+ g_str_equal (wtmp_entry.ut_name, "reboot")) {
|
|
+ shutdown_or_reboot = TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (shutdown_or_reboot) {
|
|
+ /* Set shutdown, reboot, or boot time for missing logout records */
|
|
+ g_hash_table_iter_init (&iter, logout_hash);
|
|
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
+ previous_login = (UserPreviousLogin *) value;
|
|
+
|
|
+ if (previous_login->logout_time == 0) {
|
|
+ previous_login->logout_time = wtmp_entry.ut_time;
|
|
+ }
|
|
+ }
|
|
+ g_hash_table_remove_all (logout_hash);
|
|
+ }
|
|
+
|
|
+ if (wtmp_entry.ut_name[0] == 0) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!g_hash_table_lookup_extended (login_hash,
|
|
+ wtmp_entry.ut_name,
|
|
+ &key, &value)) {
|
|
+ accounting = g_new (UserAccounting, 1);
|
|
+ accounting->frequency = 0;
|
|
+ accounting->previous_logins = NULL;
|
|
+
|
|
+ g_hash_table_insert (login_hash, g_strdup (wtmp_entry.ut_name), accounting);
|
|
+ } else {
|
|
+ accounting = value;
|
|
+ }
|
|
+
|
|
+ accounting->frequency++;
|
|
+ accounting->time = wtmp_entry.ut_time;
|
|
+
|
|
+ /* Add zero logout time to change it later on logout record */
|
|
+ previous_login = g_new (UserPreviousLogin, 1);
|
|
+ previous_login->id = g_strdup (wtmp_entry.ut_line);
|
|
+ previous_login->login_time = wtmp_entry.ut_time;
|
|
+ previous_login->logout_time = 0;
|
|
+ accounting->previous_logins = g_list_prepend (accounting->previous_logins, previous_login);
|
|
+
|
|
+ g_hash_table_insert (logout_hash, g_strdup (wtmp_entry.ut_line), previous_login);
|
|
+ }
|
|
+
|
|
+ g_hash_table_iter_init (&iter, login_hash);
|
|
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
+ UserAccounting *accounting = (UserAccounting *) value;
|
|
+ UserPreviousLogin *previous_login;
|
|
+ gboolean changed = FALSE;
|
|
+ guint64 old_login_frequency;
|
|
+ guint64 old_login_time;
|
|
+
|
|
+ user = g_hash_table_lookup (users, key);
|
|
+ if (user == NULL) {
|
|
+ g_list_free_full (accounting->previous_logins, (GDestroyNotify) user_previous_login_free);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ g_object_get (user,
|
|
+ "login-frequency", &old_login_frequency,
|
|
+ "login-time", &old_login_time,
|
|
+ NULL);
|
|
+
|
|
+ if (old_login_frequency != accounting->frequency) {
|
|
+ g_object_set (user, "login-frequency", accounting->frequency, NULL);
|
|
+ changed = TRUE;
|
|
+ }
|
|
+
|
|
+ if (old_login_time != accounting->time) {
|
|
+ g_object_set (user, "login-time", accounting->time, NULL);
|
|
+ changed = TRUE;
|
|
+ }
|
|
+
|
|
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("a(xxa{sv})"));
|
|
+ for (l = g_list_last (accounting->previous_logins); l != NULL; l = l->prev) {
|
|
+ previous_login = l->data;
|
|
+
|
|
+ builder2 = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
|
+ g_variant_builder_add (builder2, "{sv}", "type", g_variant_new_string (previous_login->id));
|
|
+ g_variant_builder_add (builder, "(xxa{sv})", previous_login->login_time, previous_login->logout_time, builder2);
|
|
+ g_variant_builder_unref (builder2);
|
|
+ }
|
|
+ g_object_set (user, "login-history", g_variant_new ("a(xxa{sv})", builder), NULL);
|
|
+ g_variant_builder_unref (builder);
|
|
+ g_list_free_full (accounting->previous_logins, (GDestroyNotify) user_previous_login_free);
|
|
+
|
|
+ if (changed)
|
|
+ user_changed (user);
|
|
+ }
|
|
+
|
|
+ g_hash_table_unref (login_hash);
|
|
+ g_hash_table_unref (logout_hash);
|
|
+}
|
|
+
|
|
const gchar *
|
|
wtmp_helper_get_path_for_monitor (void)
|
|
{
|
|
- return NULL;
|
|
+ return _PATH_WTMP;
|
|
}
|
|
|
|
#endif /* HAVE_UTMPX_H */
|