initial import from svn trunk revision 2950
diff --git a/policycoreutils/restorecond/utmpwatcher.c b/policycoreutils/restorecond/utmpwatcher.c
new file mode 100644
index 0000000..f818bbf
--- /dev/null
+++ b/policycoreutils/restorecond/utmpwatcher.c
@@ -0,0 +1,116 @@
+/*
+ * utmpwatcher.c
+ *
+ * Copyright (C) 2006 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+.*
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ *
+ * Authors:
+ * Dan Walsh <dwalsh@redhat.com>
+ *
+ *
+*/
+
+#define _GNU_SOURCE
+#include <sys/inotify.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include <limits.h>
+#include <utmp.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include "restorecond.h"
+#include "utmpwatcher.h"
+#include "stringslist.h"
+
+static struct stringsList *utmp_ptr = NULL;
+static int utmp_wd = -1;
+
+unsigned int utmpwatcher_handle(int inotify_fd, int wd)
+{
+ int changed = 0;
+ struct utmp u;
+ char *utmp_path = "/var/run/utmp";
+ struct stringsList *prev_utmp_ptr = utmp_ptr;
+ if (wd != utmp_wd)
+ return -1;
+
+ utmp_ptr = NULL;
+ FILE *cfg = fopen(utmp_path, "r");
+ if (!cfg)
+ exitApp("Error reading config file.");
+
+ while (fread(&u, sizeof(struct utmp), 1, cfg) > 0) {
+ if (u.ut_type == USER_PROCESS)
+ strings_list_add(&utmp_ptr, u.ut_user);
+ }
+ fclose(cfg);
+ if (utmp_wd >= 0)
+ inotify_rm_watch(inotify_fd, utmp_wd);
+
+ utmp_wd =
+ inotify_add_watch(inotify_fd, utmp_path, IN_MOVED_FROM | IN_MODIFY);
+ if (prev_utmp_ptr) {
+ changed = strings_list_diff(prev_utmp_ptr, utmp_ptr);
+ strings_list_free(prev_utmp_ptr);
+ }
+ return changed;
+}
+
+static void watch_file(int inotify_fd, const char *file)
+{
+ struct stringsList *ptr = utmp_ptr;
+
+ while (ptr) {
+ struct passwd *pwd = getpwnam(ptr->string);
+ if (pwd) {
+ char *path = NULL;
+ if (asprintf(&path, "%s%s", pwd->pw_dir, file) < 0)
+ exitApp("Error allocating memory.");
+ watch_list_add(inotify_fd, path);
+ free(path);
+ }
+ ptr = ptr->next;
+ }
+}
+
+void utmpwatcher_add(int inotify_fd, const char *path)
+{
+ if (utmp_ptr == NULL) {
+ utmpwatcher_handle(inotify_fd, utmp_wd);
+ }
+ watch_file(inotify_fd, path);
+}
+
+void utmpwatcher_free(void)
+{
+ if (utmp_ptr)
+ strings_list_free(utmp_ptr);
+}
+
+#ifdef TEST
+int main(int argc, char **argv)
+{
+ read_utmp();
+ return 0;
+}
+#endif