ports/sysutils/accountsservice/patches/patch-src_wtmp-helper_c

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 */