summaryrefslogtreecommitdiff
path: root/src/daemon.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-07-17 03:36:57 +0200
committerRay Strode <rstrode@redhat.com>2011-07-19 12:04:05 -0400
commit281ac4126636a7a701b95c465ab9de7762e17fdf (patch)
tree5565bba0a829af22e71c87c0737f957c29e3774b /src/daemon.c
parent4fbee1df531c0c1151874c9c1c8f1b379d9f549c (diff)
daemon: get login frequency from wtmp instead of ConsoleKit
Use the POSIX wtmpx database instead of ConsoleKit as source for calculating login frequency. This is more portable and much simpler. Also, it allows us to prepare accountsservice for the post-CK times. Minor-Updates-By: Ray Strode <rstrode@redhat.com> https://bugs.freedesktop.org/show_bug.cgi?id=39295
Diffstat (limited to 'src/daemon.c')
-rw-r--r--src/daemon.c287
1 files changed, 53 insertions, 234 deletions
diff --git a/src/daemon.c b/src/daemon.c
index a34ccfa..5f8e778 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
+#include <utmpx.h>
#include <glib.h>
#include <glib/gi18n.h>
@@ -88,7 +89,6 @@ enum {
enum {
USER_ADDED,
USER_REMOVED,
- CK_HISTORY_LOADED,
LAST_SIGNAL
};
@@ -108,7 +108,6 @@ struct DaemonPrivate {
GFileMonitor *shadow_monitor;
guint reload_id;
- guint ck_history_id;
guint autologin_id;
PolkitAuthority *authority;
@@ -205,16 +204,6 @@ daemon_class_init (DaemonClass *klass)
1,
DBUS_TYPE_G_OBJECT_PATH);
- signals[CK_HISTORY_LOADED] = g_signal_new ("ck-history-loaded",
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
dbus_g_object_type_install_info (TYPE_DAEMON,
&dbus_glib_daemon_object_info);
@@ -245,231 +234,79 @@ daemon_local_user_is_excluded (Daemon *daemon, const gchar *username, uid_t uid)
}
static void
-listify_hash_values_hfunc (gpointer key,
- gpointer value,
- gpointer user_data)
+reload_wtmp_history (Daemon *daemon)
{
- GSList **list = user_data;
-
- *list = g_slist_prepend (*list, value);
-}
-
-static gboolean
-parse_value_as_ulong (const gchar *value,
- gulong *ulongval)
-{
- gchar *end_of_valid_long;
- glong long_value;
- gulong ulong_value;
-
- errno = 0;
- long_value = strtol (value, &end_of_valid_long, 10);
-
- if (*value == '\0' || *end_of_valid_long != '\0') {
- return FALSE;
- }
-
- ulong_value = long_value;
- if (ulong_value != long_value || errno == ERANGE) {
- return FALSE;
- }
+ struct utmpx *wtmp_entry;
+ GHashTable *login_frequency_hash;
+ GHashTableIter iter;
+ gpointer key, value;
- *ulongval = ulong_value;
+ utmpxname(_PATH_WTMPX);
+ setutxent ();
- return TRUE;
-}
+ login_frequency_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
-static gboolean
-parse_ck_history_line (const gchar *line,
- gchar **user_namep,
- gulong *frequencyp)
-{
- GRegex *re;
- GMatchInfo *match_info;
- gboolean res;
- gboolean ret;
- GError *error;
+ while ((wtmp_entry = getutxent ())) {
+ if (wtmp_entry->ut_type != USER_PROCESS)
+ continue;
- ret = FALSE;
- re = NULL;
- match_info = NULL;
+ if (wtmp_entry->ut_user[0] == 0)
+ continue;
- error = NULL;
- re = g_regex_new ("(?P<username>[0-9a-zA-Z]+)[ ]+(?P<frequency>[0-9]+)", 0, 0, &error);
- if (re == NULL) {
- if (error != NULL) {
- g_critical ("%s", error->message);
- } else {
- g_critical ("Error in regex call");
+ if (daemon_local_user_is_excluded (daemon,
+ wtmp_entry->ut_user,
+ daemon->priv->minimal_uid)) {
+ g_debug ("excluding user '%s'", wtmp_entry->ut_user);
+ continue;
}
- goto out;
- }
-
- g_regex_match (re, line, 0, &match_info);
- res = g_match_info_matches (match_info);
- if (! res) {
- g_warning ("Unable to parse history: %s", line);
- goto out;
- }
+ if (!g_hash_table_lookup_extended (login_frequency_hash,
+ wtmp_entry->ut_user,
+ &key, &value)) {
+ value = GUINT_TO_POINTER (0);
+ g_hash_table_insert (login_frequency_hash,
+ g_strdup (wtmp_entry->ut_user),
+ GUINT_TO_POINTER (0));
+ } else {
+ guint frequency;
- if (user_namep != NULL) {
- *user_namep = g_match_info_fetch_named (match_info, "username");
- }
+ frequency = GPOINTER_TO_UINT (value) + 1;
- if (frequencyp != NULL) {
- char *freq;
- freq = g_match_info_fetch_named (match_info, "frequency");
- res = parse_value_as_ulong (freq, frequencyp);
- g_free (freq);
- if (! res) {
- goto out;
+ g_hash_table_insert (login_frequency_hash,
+ key,
+ GUINT_TO_POINTER (frequency));
}
- }
-
- ret = TRUE;
-
- out:
- if (match_info != NULL) {
- g_match_info_free (match_info);
- }
- if (re != NULL) {
- g_regex_unref (re);
- }
- return ret;
-}
-
-static void
-process_ck_history_line (Daemon *daemon,
- const gchar *line)
-{
- gboolean res;
- gchar *username;
- gulong frequency;
- User *user;
-
- frequency = 0;
- username = NULL;
- res = parse_ck_history_line (line, &username, &frequency);
- if (! res) {
- return;
- }
-
- if (daemon_local_user_is_excluded (daemon, username, daemon->priv->minimal_uid)) {
- g_debug ("excluding user '%s'", username);
- g_free (username);
- return;
- }
- user = daemon_local_find_user_by_name (daemon, username);
- if (user == NULL) {
- g_debug ("unable to lookup user '%s'", username);
- g_free (username);
- return;
}
+ endutxent ();
- g_object_set (user, "login-frequency", (guint64) frequency, NULL);
- g_free (username);
-}
+ g_hash_table_iter_init (&iter, login_frequency_hash);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ User *user;
+ char *username = (char *) key;
+ guint64 frequency = (guint64) GPOINTER_TO_UINT (value);
-static gboolean
-ck_history_watch (GIOChannel *source,
- GIOCondition condition,
- Daemon *daemon)
-{
- GIOStatus status;
- gboolean done = FALSE;
-
- if (condition & G_IO_IN) {
- gchar *str;
- GError *error;
-
- error = NULL;
- status = g_io_channel_read_line (source, &str, NULL, NULL, &error);
- if (error != NULL) {
- g_warning ("unable to read line: %s", error->message);
- g_error_free (error);
- }
- if (status == G_IO_STATUS_NORMAL) {
- g_debug ("history output: %s", str);
- process_ck_history_line (daemon, str);
- } else if (status == G_IO_STATUS_EOF) {
- done = TRUE;
+ user = daemon_local_find_user_by_name (daemon, username);
+ if (user == NULL) {
+ g_debug ("unable to lookup user '%s'", username);
+ continue;
}
- g_free (str);
- } else if (condition & G_IO_HUP) {
- done = TRUE;
- }
-
- if (done) {
- daemon->priv->ck_history_id = 0;
- g_signal_emit (daemon, signals[CK_HISTORY_LOADED], 0);
- return FALSE;
+ g_object_set (user, "login-frequency", frequency, NULL);
}
- return TRUE;
+ g_hash_table_foreach (login_frequency_hash, (GHFunc) g_free, NULL);
+ g_hash_table_unref (login_frequency_hash);
}
static void
-reload_ck_history (Daemon *daemon)
+listify_hash_values_hfunc (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- gchar *command;
- GError *error;
- gboolean res;
- gchar **argv;
- gint standard_out;
- GIOChannel *channel;
-
- command = g_strdup ("ck-history --frequent --session-type=''");
- g_debug ("running '%s'", command);
- error = NULL;
- if (! g_shell_parse_argv (command, NULL, &argv, &error)) {
- if (error != NULL) {
- g_warning ("Could not parse command: %s", error->message);
- g_error_free (error);
- } else {
- g_warning ("Could not parse command");
- }
- goto out;
- }
-
- error = NULL;
- res = g_spawn_async_with_pipes (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL, /* pid */
- NULL,
- &standard_out,
- NULL,
- &error);
- g_strfreev (argv);
- if (! res) {
- if (error != NULL) {
- g_warning ("Unable to run ck-history: %s", error->message);
- g_error_free (error);
- } else {
- g_warning ("Unable to run ck-history");
- }
- goto out;
- }
-
- channel = g_io_channel_unix_new (standard_out);
- g_io_channel_set_close_on_unref (channel, TRUE);
- g_io_channel_set_flags (channel,
- g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
- NULL);
- daemon->priv->ck_history_id = g_io_add_watch (channel,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc)ck_history_watch,
- daemon);
- g_io_channel_unref (channel);
+ GSList **list = user_data;
- out:
- g_free (command);
+ *list = g_slist_prepend (*list, value);
}
static gint
@@ -589,7 +426,7 @@ reload_data (Daemon *daemon)
static void
reload_users (Daemon *daemon)
{
- reload_ck_history (daemon);
+ reload_wtmp_history (daemon);
reload_passwd (daemon);
reload_data (daemon);
}
@@ -784,7 +621,7 @@ daemon_init (Daemon *daemon)
} else {
g_warning ("Unable to monitor %s: %s", PATH_SHADOW, error->message);
g_error_free (error);
- }
+ }
queue_reload_users (daemon);
queue_reload_autologin (daemon);
@@ -1057,18 +894,6 @@ finish_list_cached_users (gpointer user_data)
return FALSE;
}
-static void
-on_ck_history_loaded (Daemon *daemon,
- ListUserData *data)
-{
- /* ck-history loaded, so finish pending ListCachedUsers call */
- g_idle_add (finish_list_cached_users, data);
-
- g_signal_handlers_disconnect_by_func (daemon,
- on_ck_history_loaded,
- data);
-}
-
gboolean
daemon_list_cached_users (Daemon *daemon,
DBusGMethodInvocation *context)
@@ -1077,12 +902,7 @@ daemon_list_cached_users (Daemon *daemon,
data = list_user_data_new (daemon, context);
- if (daemon->priv->ck_history_id > 0) {
- /* loading ck-history, wait for it */
- g_signal_connect (daemon, "ck-history-loaded",
- G_CALLBACK (on_ck_history_loaded),
- data);
- } else if (daemon->priv->reload_id > 0) {
+ if (daemon->priv->reload_id > 0) {
/* reload in progress, wait a bit */
g_idle_add (finish_list_cached_users, data);
}
@@ -1488,4 +1308,3 @@ daemon_local_set_automatic_login (Daemon *daemon,
return TRUE;
}
-