Index: /trunk/Makefile.in
===================================================================
--- /trunk/Makefile.in	(revision 258)
+++ /trunk/Makefile.in	(revision 259)
@@ -123,5 +123,5 @@
 	sh_mounts.h sh_userfiles.h sh_static.h sh_prelink.h \
 	sh_processcheck.h sh_portcheck.h sh_pthread.h sh_string.h \
-	sh_log_check.h sh_log_evalrule.h
+	sh_log_check.h sh_log_evalrule.h sh_inotify.h
 
 
@@ -162,4 +162,5 @@
 	$(srcsrc)/sh_log_parse_apache.c $(srcsrc)/sh_log_evalrule.c \
 	$(srcsrc)/sh_log_check.c $(srcsrc)/dnmalloc.c \
+	$(srcsrc)/sh_inotify.c \
 	$(srcsrc)/t-test1.c
 
@@ -178,5 +179,5 @@
 	sh_log_parse_syslog.o sh_log_parse_pacct.o sh_log_parse_apache.o \
 	sh_log_parse_samba.o sh_log_evalrule.o sh_log_check.o \
-	sh_pthread.o sh_string.o dnmalloc.o
+	sh_pthread.o sh_string.o sh_inotify.o dnmalloc.o
 
 KERN = kern_head.h kern_head.c
@@ -1676,5 +1677,5 @@
 sh_forward.o: $(srcsrc)/sh_forward.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_forward.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h 
 sh_modules.o: $(srcsrc)/sh_modules.c Makefile config_xor.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utmp.h $(srcinc)/sh_mounts.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_kern.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_portcheck.h $(srcinc)/sh_logmon.h 
-sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h 
+sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h 
 sh_kern.o: $(srcsrc)/sh_kern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_kern.h sh_ks_xor.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h 
 sh_suidchk.o: $(srcsrc)/sh_suidchk.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_hash.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_schedule.h $(srcinc)/sh_calls.h 
@@ -1732,2 +1733,3 @@
 sh_nmail.o: $(srcsrc)/sh_nmail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_mail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/zAVLTree.h 
 sh_filter.o: $(srcsrc)/sh_filter.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_filter.h 
+sh_inotify.o: $(srcsrc)/sh_inotify.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/sh_mem.h $(srcinc)/slib.h $(srcinc)/sh_calls.h 
Index: /trunk/configure.ac
===================================================================
--- /trunk/configure.ac	(revision 258)
+++ /trunk/configure.ac	(revision 259)
@@ -222,5 +222,5 @@
 
 AC_CHECK_HEADERS(stddef.h libgen.h sched.h malloc.h sys/uio.h \
-	sys/mman.h sys/param.h \
+	sys/mman.h sys/param.h sys/inotify.h \
 	sys/vfs.h mntent.h \
 	sys/select.h sys/socket.h netinet/in.h \
@@ -370,5 +370,5 @@
 	strerror_r getgrgid_r getpwnam_r getpwuid_r \
 	gmtime_r localtime_r rand_r readdir_r strtok_r \
-	mincore posix_fadvise
+	mincore posix_fadvise inotify_init1
 )
 AC_CHECK_FUNC(statfs, AC_DEFINE(HAVE_STATFS) statfs="yes",  statfs="no")
Index: /trunk/depend.dep
===================================================================
--- /trunk/depend.dep	(revision 258)
+++ /trunk/depend.dep	(revision 259)
@@ -19,5 +19,5 @@
 sh_forward.o: $(srcsrc)/sh_forward.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_forward.h $(srcinc)/sh_srp.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_entropy.h $(srcinc)/sh_html.h $(srcinc)/sh_nmail.h $(srcinc)/sh_socket.h $(srcinc)/sh_static.h $(srcinc)/rijndael-api-fst.h $(srcinc)/sh_readconf.h $(srcinc)/zAVLTree.h $(srcinc)/sh_extern.h 
 sh_modules.o: $(srcsrc)/sh_modules.c Makefile config_xor.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utmp.h $(srcinc)/sh_mounts.h $(srcinc)/sh_userfiles.h $(srcinc)/sh_kern.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_portcheck.h $(srcinc)/sh_logmon.h 
-sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h 
+sh_utmp.o: $(srcsrc)/sh_utmp.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_utmp.h $(srcinc)/sh_pthread.h $(srcinc)/sh_inotify.h 
 sh_kern.o: $(srcsrc)/sh_kern.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_kern.h sh_ks_xor.h $(srcinc)/sh_unix.h $(srcinc)/sh_hash.h 
 sh_suidchk.o: $(srcsrc)/sh_suidchk.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_modules.h $(srcinc)/sh_suidchk.h $(srcinc)/sh_hash.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_schedule.h $(srcinc)/sh_calls.h 
@@ -77,2 +77,3 @@
 sh_nmail.o: $(srcsrc)/sh_nmail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_mem.h $(srcinc)/sh_mail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_string.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_filter.h $(srcinc)/sh_mail_int.h $(srcinc)/zAVLTree.h 
 sh_filter.o: $(srcsrc)/sh_filter.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_filter.h 
+sh_inotify.o: $(srcsrc)/sh_inotify.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_inotify.h $(srcinc)/sh_mem.h $(srcinc)/slib.h $(srcinc)/sh_calls.h 
Index: /trunk/depend.sum
===================================================================
--- /trunk/depend.sum	(revision 258)
+++ /trunk/depend.sum	(revision 259)
@@ -1,1 +1,1 @@
-3298738653
+2870675903
Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 258)
+++ /trunk/docs/Changelog	(revision 259)
@@ -1,2 +1,5 @@
+2.6.1:
+	* use inotify to track login/logout (sh_inotify.c, sh_utmp.c)
+
 2.6.0:
 	* don't use statvfs() for process checking on FreeBSD
@@ -8,18 +11,18 @@
 	* By default disable scanning ..namedfork/rsrc (deprecated by Apple)
 
-2.5.10:
+2.5.10 (12-10-2009):
 	* sh_suidchk.c: handle $HOME/.gvfs mount gracefully
 	* slib.c: fix race condition caused by closing a stream and the fd
 
-2.5.9c:
+2.5.9c (01-10-2009):
 	* move stale file record error message closer to problem zone
 	* sh_port2proc.c: fix flawed logic for interpreting /proc/net/udp,tcp
 	
-2.5.9b:
+2.5.9b (22-09-2009):
 	* remove stale file record when creating handle, and raise diagnostic
 	  error to find origin of stale record
 	* sh_port2proc.c: check /proc/net/upd6 for IPv6-only UDP sockets
 
-2.5.9a:
+2.5.9a (17-09-2009):
 	* fixed a race condition in closing of file handles
 
Index: /trunk/include/sh_modules.h
===================================================================
--- /trunk/include/sh_modules.h	(revision 258)
+++ /trunk/include/sh_modules.h	(revision 259)
@@ -4,4 +4,10 @@
 
 #include "sh_pthread.h"
+
+enum
+  {
+    SH_MODFL_NOTIMER = (1 << 0)
+  };
+
 
 typedef struct rconf
@@ -18,4 +24,7 @@
   /* Set by samhain to 1 on successful initialization, else 0  */
   int    initval; 
+
+  /* Flags: SH_MOD_NOTIMER                                     */
+  int    flags; 
 
   /* The initialization function. Return 0 on success.         */
Index: /trunk/src/sh_modules.c
===================================================================
--- /trunk/src/sh_modules.c	(revision 258)
+++ /trunk/src/sh_modules.c	(revision 259)
@@ -23,4 +23,5 @@
     N_("UTMP"),
     -1,
+    SH_MODFL_NOTIMER,
     sh_utmp_init,
     sh_utmp_timer,
@@ -39,4 +40,5 @@
     N_("MOUNTS"),
     -1,
+    0,
     sh_mounts_init,
     sh_mounts_timer,
@@ -55,4 +57,5 @@
     N_("USERFILES"),
     -1,
+    0,
     sh_userfiles_init,
     sh_userfiles_timer,
@@ -71,4 +74,5 @@
     N_("KERNEL"),
     -1,
+    0,
     sh_kern_init,
     sh_kern_timer,
@@ -87,4 +91,5 @@
     N_("SUIDCHECK"),
     -1,
+    0,
     sh_suidchk_init,
     sh_suidchk_timer,
@@ -103,4 +108,5 @@
     N_("PROCESSCHECK"),
     -1,
+    0,
     sh_prochk_init,
     sh_prochk_timer,
@@ -119,4 +125,5 @@
     N_("PORTCHECK"),
     -1,
+    0,
     sh_portchk_init,
     sh_portchk_timer,
@@ -135,4 +142,5 @@
     N_("LOGMON"),
     -1,
+    0,
     sh_log_check_init,
     sh_log_check_timer,
@@ -150,4 +158,5 @@
     NULL,
     -1,
+    0,
 
     NULL,
Index: /trunk/src/sh_pthread.c
===================================================================
--- /trunk/src/sh_pthread.c	(revision 258)
+++ /trunk/src/sh_pthread.c	(revision 259)
@@ -182,5 +182,6 @@
 		  pthread_testcancel();
 		}
-	      retry_msleep(1,0);
+	      if (0 == (SH_MODFL_NOTIMER & this_module->flags))
+		retry_msleep(1,0);
 	    }
 
Index: /trunk/src/sh_utmp.c
===================================================================
--- /trunk/src/sh_utmp.c	(revision 258)
+++ /trunk/src/sh_utmp.c	(revision 259)
@@ -80,4 +80,5 @@
 #include "sh_utmp.h"
 #include "sh_pthread.h"
+#include "sh_inotify.h"
 
 SH_MUTEX_EXTERN(mutex_thread_nolog);
@@ -186,4 +187,6 @@
 static char   terminated_line[UT_HOSTSIZE]; 
 #endif
+
+static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
 
 static struct SH_UTMP_S save_utmp;
@@ -519,4 +522,8 @@
 #endif
 
+#if defined(HAVE_PTHREAD)
+static sh_watches inotify_watch;
+#endif
+
 int sh_utmp_end ()
 {
@@ -540,10 +547,15 @@
   set_defaults();
   init_done          = 0;
+
+  sh_inotify_remove(&inotify_watch);
+
   SL_RETURN( (0), _("sh_utmp_end"));
 }
 
+
 int sh_utmp_reconf()
 {
   set_defaults();
+  sh_inotify_remove(&inotify_watch);
   return 0;
 }
@@ -557,4 +569,7 @@
 int sh_utmp_timer (time_t tcurrent)
 {
+#if !defined(HAVE_PTHREAD)
+  retry_msleep(1, 0);
+
   if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval)
     {
@@ -563,4 +578,25 @@
     }
   return 0;
+#else
+  int errnum = 0;
+  
+  if (sh.flag.checkSum != SH_CHECK_INIT)
+    sh_inotify_wait_for_change(mode_path[1], &inotify_watch, 
+			       &errnum, ShUtmpInterval);
+
+  lastcheck  = tcurrent;
+  if (SH_INOTIFY_ERROR(errnum))
+    {
+      char ebuf[SH_ERRBUF_SIZE];
+
+      SH_MUTEX_LOCK(mutex_thread_nolog);
+      sh_error_message(errnum, ebuf, sizeof(ebuf));
+      sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, errnum, MSG_E_SUBGEN,
+		       ebuf,
+		       _("sh_utmp_timer") );
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);    
+    }
+  return -1;
+#endif
 }
 
@@ -574,5 +610,10 @@
   SL_ENTER(_("sh_utmp_check"));
   if (ShUtmpActive == BAD)
-    SL_RETURN( (-1), _("sh_utmp_check"));
+    {
+#if defined(HAVE_PTHREAD)
+      sh_inotify_remove(&inotify_watch);
+#endif
+      SL_RETURN( (-1), _("sh_utmp_check"));
+    }
   SH_MUTEX_LOCK(mutex_thread_nolog);
   sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
@@ -746,23 +787,19 @@
  *    - link user.ut_record   -> log_record
  */
+
 #ifdef HAVE_UTTYPE  
 static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
 {
-  if (in_utline != NULL)
-    {
-      if (0 == sl_strncmp(in_utline, _("ttyp"), 4))
-	{ return 0; }
-      else if (0 == sl_strncmp(in_utline, _("ttyq"), 4))
-	{ return 0; }
-    }
-  if (in_uthost != NULL   && 
+
+  if (in_uthost != NULL   &&
+      in_utline != NULL   &&
       in_uthost[0] == ':' && 
       in_uthost[1] == '0' && 
-      in_uthost[2] == '\0')
-    {
-      /* return 0; */
-      return 1;  /* actually does not seem portable, not even among linuxes */
-    }
-  return 1;
+      0 == sl_strncmp(in_utline, _("pts/"), 4))
+    {
+      return 1;
+    }
+
+  return 0;
 }
 #endif
@@ -884,5 +921,5 @@
 	SH_MUTEX_UNLOCK(mutex_thread_nolog);
       } else
-	if (0 != sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
+	if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
 	  {       
 	    status = sh_utmp_login_a((char*)user->name);
@@ -923,33 +960,39 @@
       if (user != NULL)
 	{
-	  status = sh_utmp_login_r((char*)user->name);
-	  SH_MUTEX_LOCK(mutex_thread_nolog);
-	  (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
-	  sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
+#if defined(__linux__)
+	  if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) {
+#endif
+	    status = sh_utmp_login_r((char*)user->name);
+	    SH_MUTEX_LOCK(mutex_thread_nolog);
+	    (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
+	    sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
 #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
-			   MSG_UT_LG3X,
+			     MSG_UT_LG3X,
 #elif defined(HAVE_UTHOST)
-			   MSG_UT_LG3A,
-#else
-			   MSG_UT_LG3B,
-#endif
-			   user->name,
-			   user->ut_tty,
+			     MSG_UT_LG3A,
+#else
+			     MSG_UT_LG3B,
+#endif
+			     user->name,
+			     user->ut_tty,
 #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
-			   user->ut_host,
-			   user->ut_ship,
+			     user->ut_host,
+			     user->ut_ship,
 #elif defined(HAVE_UTHOST)
-			   user->ut_host,
-#endif
-			   ttt,
-			   status
-			   );
-	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
-	  userold->next = user->next;
-	  if (user == userlist)
-	    userlist = user->next;
-	  sh_utmp_logout_morechecks((struct log_user *)user);
-	  SH_FREE((struct log_user *)user);
-	  user = NULL;
+			     user->ut_host,
+#endif
+			     ttt,
+			     status
+			     );
+	    SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	    userold->next = user->next;
+	    if (user == userlist)
+	      userlist = user->next;
+	    sh_utmp_logout_morechecks((struct log_user *)user);
+	    SH_FREE((struct log_user *)user);
+	    user = NULL;
+#if defined(__linux__)
+	  }
+#endif
 	}
       else
@@ -1053,6 +1096,4 @@
 static unsigned long lastread = 0;
 
-static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
-
 static void sh_utmp_check_internal (int mode)
 {
