r11064 - in prelude-lml/trunk: . src src/include

[email protected]
Newsgroups gmane.comp.security.ids.prelude.cvs
Message-ID <[email protected]>
Author: yoann
Date: 2008-10-15 15:00:25 +0200 (Wed, 15 Oct 2008)
New Revision: 11064

Modified:
   prelude-lml/trunk/Makefile.am
   prelude-lml/trunk/configure.in
   prelude-lml/trunk/src/Makefile.am
   prelude-lml/trunk/src/file-server.c
   prelude-lml/trunk/src/include/file-server.h
   prelude-lml/trunk/src/include/lml-options.h
   prelude-lml/trunk/src/lml-options.c
   prelude-lml/trunk/src/prelude-lml.c
   prelude-lml/trunk/src/regex.c
Log:
Deprecate Gamin/FAM support in favor of libev. The previous implementation
had problem on SELinux enabled system. This remove a lot of code working
around FAM specific issue. Additionally, we use libev for monitoring the
UDP server socket.

The metadata format has changed, and we now use Gcrypt to generate a checksum,
this provide a nice performance improvement by preventing the ftruncate()
syscall prior saving metadata.

When an user specify a file to be monitored that isn't available for reading,
use libev to be notified of this file stat change anyway, until it can be
monitored.

Include 'original' file information in IDMEF generated alert for logfile
modification.

Make sure we use FILE_SERVER_METADATA_FLAGS_LAST when neither HEAD/TAIL
metadata are specified (fix a bug with --metadata=nowrite).

Rely on the kernel in place of our own function for checking file acces,
this should fix #291.


Modified: prelude-lml/trunk/Makefile.am
===================================================================
--- prelude-lml/trunk/Makefile.am	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/Makefile.am	2008-10-15 13:00:25 UTC (rev 11064)
@@ -1,7 +1,7 @@
 DISTCHECK_CONFIGURE_FLAGS = --enable-unsupported-rulesets
 
 ACLOCAL_AMFLAGS = -I m4 -I libmissing/m4
-SUBDIRS = libmissing plugins src tests
+SUBDIRS = libev libmissing plugins src tests
 
 preludeconfdir = $(configdir)
 EXTRA_DIST = plugins.rules prelude-lml.conf config.h \

Modified: prelude-lml/trunk/configure.in
===================================================================
--- prelude-lml/trunk/configure.in	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/configure.in	2008-10-15 13:00:25 UTC (rev 11064)
@@ -131,50 +131,19 @@
 
 
 
-dnl **************************************************
-dnl * Check for FAM.                                 *
-dnl **************************************************
+dnl ********************************************************
+dnl * Configure embedded libev                             *
+dnl ********************************************************
 
-AC_ARG_WITH(fam, AC_HELP_STRING(--with-fam@<:@=PATH@:>@, Path where FAM is installed @<:@default=auto@:>@),
-            fam_required=true, with_fam=yes)
+AC_DEFINE_UNQUOTED(EV_PERIODIC_ENABLE, 0, Disable unused libev periodic timers)
+AC_DEFINE_UNQUOTED(EV_IDLE_ENABLE, 0, Disable unused libev idle watchers)
+AC_DEFINE_UNQUOTED(EV_FORK_ENABLE, 0, Disable unused libev fork watchers)
+AC_DEFINE_UNQUOTED(EV_EMBED_ENABLE, 0, Disable unused libev embed watchers)
+AC_DEFINE_UNQUOTED(EV_MULTIPLICITY, 0, Disable support for multiple libev event loop)
 
-if test x$with_fam != xno; then
-   old_LIBS=$LIBS
-   old_LDFLAGS=$LDFLAGS
-   old_CPPFLAGS=$CPPFLAGS
+m4_include([libev/libev.m4])
 
-   if test x$with_fam != xyes; then
-      FAM_LIBS="-L$with_fam/lib"
-      FAM_CFLAGS="-I$with_fam/include"
-      LDFLAGS="$LDFLAGS -L$with_fam/lib"
-      CPPFLAGS="$CPPFLAGS -I$with_fam/include"
-   fi
 
-   AC_CHECK_HEADER(fam.h, , fam_header_ok="no")
-   AC_CHECK_LIB(fam, FAMOpen, , fam_lib_ok="no")
-
-   LIBS="$old_LIBS"
-   LDFLAGS="$old_LDFLAGS"
-   CPPFLAGS="$old_CPPFLAGS"
-
-   if test "$fam_header_ok" = "no" -o "$fam_lib_ok" = "no"; then
-        FAM_LIBS=""
-        FAM_CFLAGS=""
-        FAM_LDFLAGS=""
-        with_fam=no;
-   else
-        with_fam=yes;
-        FAM_LIBS="-lfam"
-        AC_DEFINE(HAVE_FAM, , Tell whether FAM support should be compiled in)
-   fi
-fi
-
-AC_SUBST(FAM_LIBS)
-AC_SUBST(FAM_CFLAGS)
-AC_SUBST(FAM_LDFLAGS)
-AM_CONDITIONAL(HAVE_FAM, test x$with_fam = xyes)
-
-
 dnl **************************************************
 dnl * Setup build variable                           *
 dnl **************************************************
@@ -208,6 +177,7 @@
 plugins.rules
 
 Makefile
+libev/Makefile
 libmissing/Makefile
 libmissing/tests/Makefile
 

Modified: prelude-lml/trunk/src/Makefile.am
===================================================================
--- prelude-lml/trunk/src/Makefile.am	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/Makefile.am	2008-10-15 13:00:25 UTC (rev 11064)
@@ -1,11 +1,11 @@
 SUBDIRS = include
 
-AM_CPPFLAGS = -I$(srcdir)/include/ -I$(top_srcdir)/libmissing -I$(top_builddir)/libmissing @LIBPRELUDE_CFLAGS@ @PCRE_CFLAGS@ @FAM_CFLAGS@
+AM_CPPFLAGS = -I$(srcdir)/include/ -I$(top_srcdir)/libmissing -I$(top_builddir)/libmissing -I$(top_srcdir)/libev @LIBPRELUDE_CFLAGS@ @PCRE_CFLAGS@
 AM_CFLAGS = @GLOBAL_CFLAGS@
 
 bin_PROGRAMS = prelude-lml
-prelude_lml_LDADD = @LIBPRELUDE_LIBS@ @PCRE_LIBS@ @FAM_LIBS@ $(top_builddir)/libmissing/libmissing.la
-prelude_lml_LDFLAGS = @LIBPRELUDE_LDFLAGS@ @FAM_LDFLAGS@ -export-dynamic \
+prelude_lml_LDADD = @LIBPRELUDE_LIBS@ @PCRE_LIBS@ $(top_builddir)/libev/libev.la $(top_builddir)/libmissing/libmissing.la
+prelude_lml_LDFLAGS = @LIBPRELUDE_LDFLAGS@ -export-dynamic \
         "-dlopen" $(top_builddir)/plugins/debug/debug.la \
         "-dlopen" $(top_builddir)/plugins/pcre/pcre.la
 

Modified: prelude-lml/trunk/src/file-server.c
===================================================================
--- prelude-lml/trunk/src/file-server.c	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/file-server.c	2008-10-15 13:00:25 UTC (rev 11064)
@@ -34,6 +34,8 @@
 #include <errno.h>
 #include <assert.h>
 
+#include <gcrypt.h>
+
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
@@ -45,13 +47,12 @@
 # endif
 #endif
 
-#ifdef HAVE_FAM
- #include <fam.h>
-#endif
+#include "ev.h"
 
 #include <libprelude/prelude.h>
 #include <libprelude/prelude-timer.h>
 #include <libprelude/prelude-log.h>
+#include <libprelude/prelude-extract.h>
 
 #include "prelude-lml.h"
 #include "regex.h"
@@ -85,10 +86,12 @@
 /*
  * Logfile metadata stuff.
  */
-#define METADATA_MAXSIZE 8192
+#define METADATA_SIZE 12
+#define METADATA_CHECKSUM_SIZE 4
+#define METADATA_CHECKSUM_TYPE GCRY_MD_CRC32
+
 #define LOG_LINE_MAXSIZE 65535
 
-
 #define LOGFILE_RENAME_CLASS   "Log file rename"
 #define LOGFILE_DELETION_CLASS "Log file deletion"
 #define LOGFILE_DELETION_IMPACT "An attacker might have erased the logfile,"               \
@@ -99,7 +102,6 @@
                                     "to remove the trace he left."
 
 
-
 typedef struct {
         prelude_list_t list;
 
@@ -118,55 +120,86 @@
         uint64_t need_more_read;
         uint64_t last_size;
 
-        time_t last_mtime;
-
-#ifdef HAVE_FAM
-        FAMRequest fam_request;
-#endif
+        ev_stat event;
+        int prev_errno;
 } monitor_fd_t;
 
 
-
+static void libev_stat_cb(ev_stat *st, int revents);
+static int check_logfile_data(monitor_fd_t *monitor, struct stat *st);
 void _lml_handle_signal_if_needed(void);
 
+extern lml_config_t config;
 
-#ifdef HAVE_FAM
 
-static int fam_setup_monitor(monitor_fd_t *monitor);
-static FAMConnection fc;
+static PRELUDE_LIST(active_fd_list);
+static PRELUDE_LIST(inactive_fd_list);
+static unsigned int max_rotation_size_offset = DEFAULT_MAX_ROTATION_SIZE_OFFSET;
+static unsigned int max_rotation_time_offset = DEFAULT_MAX_ROTATION_TIME_OFFSET;
+static file_server_metadata_flags_t metadata_flags = FILE_SERVER_METADATA_FLAGS_LAST;
 
-#endif
 
 
+static int stat_to_file(monitor_fd_t *fd, struct stat *st, idmef_target_t *target, idmef_file_category_t category)
+{
+        int ret;
+        idmef_time_t *time;
+        idmef_file_t *file;
+        idmef_inode_t *inode;
+        prelude_string_t *string;
+        const char *fname, *fptr;
 
-static int batch_mode = 0;
-static int fam_initialized = 0;
-static file_server_metadata_flags_t metadata_flags = FILE_SERVER_METADATA_FLAGS_LAST;
+        ret = idmef_target_new_file(target, &file, -1);
+        if ( ret < 0 )
+                return -1;
 
-extern lml_config_t config;
+        idmef_file_set_category(file, category);
+        idmef_file_set_data_size(file, st->st_size);
 
+        ret = idmef_file_new_inode(file, &inode);
+        if ( ret < 0 )
+                return -1;
 
-static PRELUDE_LIST(active_fd_list);
-static PRELUDE_LIST(inactive_fd_list);
-static unsigned int max_rotation_size_offset = DEFAULT_MAX_ROTATION_SIZE_OFFSET;
-static unsigned int max_rotation_time_offset = DEFAULT_MAX_ROTATION_TIME_OFFSET;
+        idmef_inode_set_number(inode, st->st_ino);
 
+        ret = idmef_file_new_name(file, &string);
+        if ( ret < 0 )
+                return -1;
 
+        fname = lml_log_source_get_name(fd->source);
+        fptr = strrchr(fname, '/');
+        prelude_string_set_ref(string, (fptr) ? (fptr + 1) : fname);
 
-static void logfile_alert(monitor_fd_t *fd, struct stat *st,
+        ret = idmef_file_new_path(file, &string);
+        if ( ret < 0 )
+                return -1;
+        prelude_string_set_ref(string, fname);
+
+        ret = idmef_file_new_access_time(file, &time);
+        if ( ret < 0 )
+                return -1;
+
+        idmef_time_set_sec(time, st->st_atime);
+
+        ret = idmef_file_new_modify_time(file, &time);
+        if ( ret < 0 )
+                return -1;
+
+        idmef_time_set_sec(time, st->st_mtime);
+
+        return 0;
+}
+
+
+static void logfile_alert(monitor_fd_t *fd, struct stat *st_old, struct stat *st_new,
                           idmef_classification_t *classification, idmef_impact_t *impact)
 {
         int ret;
-        char buf[256], *ptr;
-        idmef_file_t *file;
-        idmef_time_t *time;
-        idmef_inode_t *inode;
         lml_log_entry_t *log_entry;
         idmef_alert_t *alert;
         idmef_target_t *target;
         idmef_message_t *message;
         idmef_assessment_t *assessment;
-        prelude_string_t *string;
 
         log_entry = lml_log_entry_new();
         if ( ! log_entry )
@@ -189,43 +222,12 @@
         if ( ret < 0 )
                 goto err;
 
-        ret = idmef_target_new_file(target, &file, -1);
-        if ( ret < 0 )
+        if ( stat_to_file(fd, st_old, target, IDMEF_FILE_CATEGORY_ORIGINAL) < 0 )
                 goto err;
 
-        idmef_file_set_category(file, IDMEF_FILE_CATEGORY_CURRENT);
-        idmef_file_set_data_size(file, st->st_size);
-
-        ret = idmef_file_new_inode(file, &inode);
-        if ( ret < 0 )
+        if ( stat_to_file(fd, st_new, target, IDMEF_FILE_CATEGORY_CURRENT) < 0 )
                 goto err;
 
-        idmef_inode_set_number(inode, st->st_ino);
-        snprintf(buf, sizeof(buf), "%s", lml_log_source_get_name(fd->source));
-
-        ptr = strrchr(buf, '/');
-        ret = idmef_file_new_name(file, &string);
-        if ( ret < 0 )
-                goto err;
-        prelude_string_set_ref(string, ptr ? (ptr + 1) : buf);
-
-        ret = idmef_file_new_path(file, &string);
-        if ( ret < 0 )
-                goto err;
-        prelude_string_set_ref(string, buf);
-
-        ret = idmef_file_new_access_time(file, &time);
-        if ( ret < 0 )
-                goto err;
-
-        idmef_time_set_sec(time, st->st_atime);
-
-        ret = idmef_file_new_modify_time(file, &time);
-        if ( ret < 0 )
-                goto err;
-
-        idmef_time_set_sec(time, st->st_mtime);
-
         ret = idmef_alert_new_assessment(alert, &assessment);
         if ( ret < 0 )
                 goto err;
@@ -242,9 +244,7 @@
 
 
 
-
-
-static void logfile_modified_alert(monitor_fd_t *monitor, struct stat *st)
+static void logfile_modified_alert(monitor_fd_t *monitor, struct stat *st_old, struct stat *st_new)
 {
         int ret;
         prelude_string_t *str;
@@ -282,71 +282,58 @@
         }
         prelude_string_set_constant(str, LOGFILE_MODIFICATION_IMPACT);
 
-        logfile_alert(monitor, st, classification, impact);
+        logfile_alert(monitor, st_old, st_new, classification, impact);
 }
 
 
-
-
-static int file_metadata_read(monitor_fd_t *monitor, uint64_t *start, char **sumline, size_t size)
+static int file_metadata_read(monitor_fd_t *monitor, uint64_t *start, unsigned char **buf)
 {
-        int line = 0, ret;
-        char *offptr, *buf;
+        ssize_t ret;
+        struct stat st;
 
-        rewind(monitor->metadata_fd);
-
-        *start = 0;
-        buf = *sumline;
-        *sumline = NULL;
-
-        if ( ! fgets(buf, size, monitor->metadata_fd) )
+        if ( fstat(fileno(monitor->metadata_fd), &st) < 0 ) {
+                prelude_log(PRELUDE_LOG_WARN, "fstat failed : %s.\n", strerror(errno));
                 return -1;
+        }
 
-        offptr = strchr(buf, ':');
-        if ( ! offptr ) {
-                prelude_log(PRELUDE_LOG_WARN, "%s:%d: Invalid metadata file.\n", lml_log_source_get_name(monitor->source), line);
+        if ( st.st_size != METADATA_SIZE ) {
+                /* old format, truncate. */
                 ftruncate(fileno(monitor->metadata_fd), 0);
                 return -1;
         }
 
-        *offptr++ = '\0';
+        rewind(monitor->metadata_fd);
 
-        ret = sscanf(buf, "%" PRELUDE_SCNu64, start);
-        if ( ret != 1 ) {
-                prelude_log(PRELUDE_LOG_WARN, "error reading metadata file offset.\n");
+        ret = fread(*buf, 1, METADATA_SIZE, monitor->metadata_fd);
+        if ( ret != METADATA_SIZE )
                 return -1;
-        }
 
-        *sumline = offptr;
+        *start = prelude_align_uint64(*buf);
+        *buf = *buf + sizeof(uint64_t);
 
         return 0;
 }
 
 
-
-
 static int file_metadata_save(monitor_fd_t *monitor, uint64_t offset)
 {
-        int len, ret;
-        char buf[METADATA_MAXSIZE];
+        int ret;
+        unsigned char buf[METADATA_SIZE];
 
         if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_NO_WRITE )
                 return 0;
 
-        len = snprintf(buf, sizeof(buf), "%" PRELUDE_PRIu64 ":%s\n", offset, prelude_string_get_string(monitor->buf));
-        if ( len >= sizeof(buf) || len < 0 )
-                return -1;
+        assert(gcry_md_get_algo_dlen(METADATA_CHECKSUM_TYPE) + sizeof(offset) == sizeof(buf));
 
+        memcpy(buf, &offset, sizeof(offset));
+        gcry_md_hash_buffer(METADATA_CHECKSUM_TYPE, buf + sizeof(offset),
+                            prelude_string_get_string(monitor->buf),
+                            prelude_string_get_len(monitor->buf));
+
         rewind(monitor->metadata_fd);
 
-        ret = ftruncate(fileno(monitor->metadata_fd), 0);
+        ret = fwrite(buf, 1, sizeof(buf), monitor->metadata_fd);
         if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_ERR, "could not truncate metadata file: %s.\n", strerror(errno));
-                return -1;
-        }
-
-        ret = fwrite(buf, 1, len, monitor->metadata_fd);
-        if ( ret < 0 ) {
                 prelude_log(PRELUDE_LOG_ERR, "could not write metadata file: %s.\n", strerror(errno));
                 return -1;
         }
@@ -356,18 +343,28 @@
 
 
 
+static int verify_metadata_checksum(const char *log, unsigned char *metadata_sum)
+{
+        unsigned char sum[METADATA_CHECKSUM_SIZE];
+
+        assert(gcry_md_get_algo_dlen(METADATA_CHECKSUM_TYPE) == sizeof(sum));
+        gcry_md_hash_buffer(METADATA_CHECKSUM_TYPE, sum, log, strlen(log) - 1);
+
+        return memcmp(sum, metadata_sum, sizeof(sum));
+}
+
 static int file_metadata_get_position(monitor_fd_t *monitor)
 {
-        uint64_t offset;
+        uint64_t offset = 0;
+        char buf[8192];
         struct stat st;
         const char *filename;
         int ret, have_metadata = 0;
-        char buf[1024], sumline[METADATA_MAXSIZE], *sumptr;
+        unsigned char msum[METADATA_SIZE], *sumptr = msum;
 
-        sumptr = sumline;
         filename = lml_log_source_get_name(monitor->source);
 
-        ret = file_metadata_read(monitor, &offset, &sumptr, sizeof(sumline));
+        ret = file_metadata_read(monitor, &offset, &sumptr);
         if ( ret == 0 )
                 have_metadata = 1;
 
@@ -378,7 +375,6 @@
         }
 
         monitor->last_size = st.st_size;
-        monitor->last_mtime = st.st_mtime;
 
         if ( ! have_metadata ) {
                 prelude_log(PRELUDE_LOG_INFO, "%s: No metadata available, starting from tail.\n", filename);
@@ -401,14 +397,14 @@
         /*
          * If the metadata checksum does not match, the file was probably rotated.
          */
-        if ( ! fgets(buf, sizeof(buf), monitor->fd) || strcmp(buf, sumptr) != 0 ) {
+        if ( ! fgets(buf, sizeof(buf), monitor->fd) || verify_metadata_checksum(buf, sumptr) != 0 ) {
                 prelude_log(PRELUDE_LOG_INFO, "%s: log file was rotated, starting from head.\n", filename);
                 monitor->last_size = 0;
                 return fseek(monitor->fd, 0, SEEK_SET);
         }
 
         monitor->last_size = offset;
-        monitor->last_size += strlen(sumptr);
+        monitor->last_size += strlen(buf);
 
         prelude_log(PRELUDE_LOG_INFO, "%s: resuming log analyzis at offset %" PRELUDE_PRIu64 ".\n",
                     filename, monitor->last_size);
@@ -505,7 +501,6 @@
 
 
 
-
 static int check_logfile_data(monitor_fd_t *monitor, struct stat *st)
 {
         off_t len, ret;
@@ -556,7 +551,6 @@
 
 
 
-
 static monitor_fd_t *monitor_new(lml_log_source_t *ls)
 {
         int ret;
@@ -577,14 +571,10 @@
                 return NULL;
         }
 
-#ifdef HAVE_FAM
-        ret = fam_setup_monitor(new);
-        if ( ret < 0 ) {
-                free(new);
-                return NULL;
-        }
-#endif
+        ev_stat_init(&new->event, libev_stat_cb, lml_log_source_get_name(new->source), 1);
+        new->event.data = new;
 
+        ev_stat_start(&new->event);
         prelude_list_add(&inactive_fd_list, &new->list);
 
         return new;
@@ -592,22 +582,6 @@
 
 
 
-#if 0
-static void monitor_destroy(monitor_fd_t *monitor)
-{
-        if ( monitor->fd )
-                fclose(monitor->fd);
-
-        prelude_list_del(&monitor->list);
-
-        free(monitor->file);
-
-        free(monitor);
-}
-#endif
-
-
-
 static int monitor_set_position(monitor_fd_t *monitor, const char *filename, int fd)
 {
         int ret = 0;
@@ -618,13 +592,17 @@
         monitor->need_position = FALSE;
 
         if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_LAST )
-                return file_metadata_get_position(monitor);
+                return file_metadata_get_position(monitor) >= 0 ? 1 : -1;
 
-        else if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_HEAD )
+        else if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_HEAD ) {
+                prelude_log(PRELUDE_LOG_INFO, "%s: user requested starting from head.\n", filename);
                 ret = fseek(monitor->fd, 0, SEEK_SET);
+        }
 
-        else if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_TAIL )
+        else if ( metadata_flags & FILE_SERVER_METADATA_FLAGS_TAIL ) {
+                prelude_log(PRELUDE_LOG_INFO, "%s: user requested starting from tail.\n", filename);
                 ret = fseek(monitor->fd, 0, SEEK_END);
+        }
 
         if ( ret < 0 ) {
                 prelude_log(PRELUDE_LOG_ERR, "%s: error seeking to the %s of the file: %s.\n",
@@ -633,7 +611,7 @@
                 return -1;
         }
 
-        return ret;
+        return 1;
 }
 
 
@@ -648,10 +626,20 @@
                 monitor->fd = stdin;
         else {
                 monitor->fd = fopen(filename, "r");
-                if ( ! monitor->fd )
+                if ( ! monitor->fd ) {
+                        if ( errno == ENOENT && monitor->prev_errno != errno )
+                                prelude_log(PRELUDE_LOG_WARN, "%s does not exist.\n", filename);
+
+                        else if ( errno == EACCES && monitor->prev_errno != errno )
+                                prelude_log(PRELUDE_LOG_WARN, "%s is not available for reading to uid %d/gid %d.\n",
+                                            filename, getuid(), getgid());
+
+                        monitor->prev_errno = errno;
                         return -1;
+                }
 
                 fd = fileno(monitor->fd);
+
 #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
                 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 #endif
@@ -659,6 +647,9 @@
                 ret = monitor_set_position(monitor, filename, fd);
                 if ( ret < 0 )
                         return -1;
+
+                if ( ret == 0 )
+                        prelude_log(PRELUDE_LOG_INFO, "%s: now available for monitoring.\n", filename);
         }
 
         ret = prelude_string_new(&monitor->buf);
@@ -668,7 +659,6 @@
         }
 
         monitor->need_more_read = 0;
-
         prelude_list_del(&monitor->list);
         prelude_list_add_tail(&active_fd_list, &monitor->list);
 
@@ -684,7 +674,6 @@
         fclose(monitor->fd);
         monitor->fd = NULL;
         monitor->last_size = 0;
-        monitor->last_mtime = 0;
 
         prelude_list_del(&monitor->list);
         prelude_list_add_tail(&inactive_fd_list, &monitor->list);
@@ -692,34 +681,20 @@
 
 
 
-static void try_reopening_inactive_monitor(void)
-{
-        prelude_list_t *tmp, *bkp;
-
-        prelude_list_for_each_safe(&inactive_fd_list, tmp, bkp)
-                monitor_open(prelude_list_entry(tmp, monitor_fd_t, list));
-}
-
-
-
-
 /*
  * This won't protect against replacement of log entry by garbage,
  * Unfortunnaly, there is no way it can be done cleanly, or it would
  * cause heavy performance problem. The best solution may be to centralize
  * the logging on a remote host.
  */
-static void check_modification_time(monitor_fd_t *monitor, struct stat *st)
+static void check_modification_time(monitor_fd_t *monitor, struct stat *prev, struct stat *st)
 {
         int ret;
-        time_t old_mtime = monitor->last_mtime;
 
-        monitor->last_mtime = st->st_mtime;
-
-        if ( st->st_mtime >= old_mtime && st->st_size >= monitor->last_size )
+        if ( st->st_mtime >= prev->st_mtime && st->st_size >= monitor->last_size )
                 return; /* everythings sound okay */
 
-        logfile_modified_alert(monitor, st);
+        logfile_modified_alert(monitor, prev, st);
 
         /*
          * If the logfile has been modified, we reposition the current
@@ -779,12 +754,12 @@
 
 
 
-static int is_file_already_used(monitor_fd_t *monitor, struct stat *st)
+static int is_file_already_used(monitor_fd_t *monitor, struct stat *st_old, struct stat *st_new)
 {
         int ret;
         char buf[1024];
         int toff, soff;
-        struct stat st_new;
+        struct stat st;
         const char *filename, *ctxt;
         idmef_impact_t *impact;
         idmef_classification_t *classification;
@@ -792,29 +767,24 @@
 
         filename = lml_log_source_get_name(monitor->source);
 
+        if ( st_new->st_nlink > 0 )
+                return 0;
+
+        fstat(fileno(monitor->fd), &st);
+
         /*
          * test if the file has been removed
          */
-        if ( st->st_nlink > 0 ) {
-                if ( stat(filename, &st_new) == 0 ) {
-                        /*
-                         * test if the file has been renamed
-                         */
-                        if ( st->st_ino == st_new.st_ino )
-                                return 0;
-
-                        monitor_close(monitor);
-                        monitor_open(monitor);
-                }
-                else monitor_close(monitor);
-                prelude_log(PRELUDE_LOG_INFO, "log file %s has been renamed.\n", filename);
+        if ( st.st_nlink > 0 && st_new->st_nlink == 0 ) {
+                prelude_log(PRELUDE_LOG_INFO, "%s: has been renamed.\n", filename);
                 ctxt = LOGFILE_RENAME_CLASS;
         } else {
-                prelude_log(PRELUDE_LOG_INFO, "log file %s has been deleted.\n", filename);
-                monitor_close(monitor);
+                prelude_log(PRELUDE_LOG_INFO, "%s: has been deleted.\n", filename);
                 ctxt = LOGFILE_DELETION_CLASS;
         }
 
+        monitor_close(monitor);
+
         ret = idmef_classification_new(&classification);
         if ( ret < 0 )
                 return -1;
@@ -836,8 +806,8 @@
         idmef_impact_set_type(impact, IDMEF_IMPACT_TYPE_FILE);
         idmef_impact_set_completion(impact, IDMEF_IMPACT_COMPLETION_SUCCEEDED);
 
-        soff = get_rotation_size_offset(monitor, st);
-        toff = get_rotation_time_offset(monitor, st);
+        soff = get_rotation_size_offset(monitor, st_new);
+        toff = get_rotation_time_offset(monitor, st_new);
 
         if ( toff <= max_rotation_time_offset|| soff <= max_rotation_size_offset ) {
                 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_INFO);
@@ -854,310 +824,71 @@
                 prelude_string_set_ref(str, buf);
         }
 
-        logfile_alert(monitor, st, classification, impact);
+        logfile_alert(monitor, st_old, st_new, classification, impact);
 
         return -1;
 }
 
-static int process_file_event(monitor_fd_t *monitor)
+
+
+static void libev_stat_cb(ev_stat *st, int revents)
 {
         int ret;
-        struct stat st;
+        monitor_fd_t *monitor = st->data;
 
-        ret = fstat(fileno(monitor->fd), &st);
-        if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_ERR, "couldn't fstat '%s'.\n", lml_log_source_get_name(monitor->source));
-                return -1;
-        }
+        if ( ! monitor->fd )
+                if ( monitor_open(monitor) < 0 )
+                        return;
 
         if ( monitor->fd != stdin ) {
-                ret = is_file_already_used(monitor, &st);
+                ret = is_file_already_used(monitor, &st->prev, &st->attr);
                 if ( ret < 0 )
-                        return -1;
+                        return;
         }
 
         /*
          * check mtime consistency.
          */
-        check_modification_time(monitor, &st);
+        check_modification_time(monitor, &st->prev, &st->attr);
 
         /*
          * read and analyze available data.
          */
-        return check_logfile_data(monitor, &st);
+        check_logfile_data(monitor, &st->attr);
 }
 
 
-#ifdef HAVE_FAM
-
-static int get_expected_event(FAMConnection *fc, int eventno)
-{
-        int ret;
-        fd_set fds;
-        FAMEvent event;
-        struct timeval tv;
-
-        FD_ZERO(&fds);
-        FD_SET(fc->fd, &fds);
-
-        tv.tv_sec = 3;
-        tv.tv_usec = 0;
-
-        while ( ! FAMPending(fc) ) {
-                ret = select(fc->fd + 1, &fds, NULL, NULL, &tv);
-                if ( ret <= 0 )
-                        return -1;
-        }
-
-        /*
-         * Wait for the notification started event.
-         */
-        ret = FAMNextEvent(fc, &event);
-        if ( ret < 0 || event.code != eventno )
-                return -1;
-
-        return 0;
-}
-
-
-
-static int check_fam_writev_bug(FAMConnection *fc)
-{
-        int ret, fd;
-        FAMRequest fr;
-        char buf[1024];
-        struct iovec iov[1];
-        char teststring[] = "testfam";
-
-        snprintf(buf, sizeof(buf), "%s/testfam.XXXXXX", P_tmpdir);
-
-        fd = mkstemp(buf);
-        if ( fd < 0 ) {
-                prelude_log(PRELUDE_LOG_ERR, "error creating unique temporary filename: %s.\n", strerror(errno));
-                return -1;
-        }
-
-        ret = FAMMonitorFile(fc, buf, &fr, NULL);
-        if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_WARN, "error creating FAM monitor for %s: %s.\n", buf, FamErrlist[FAMErrno]);
-                close(fd);
-                return -1;
-        }
-
-        ret = get_expected_event(fc, FAMExists);
-        if ( ret < 0 )
-                goto err;
-
-        ret = get_expected_event(fc, FAMEndExist);
-        if ( ret < 0 )
-                goto err;
-
-        iov[0].iov_len = sizeof(teststring);
-        iov[0].iov_base = teststring;
-
-        ret = writev(fd, iov, 1);
-        if ( ret != sizeof(teststring) ) {
-                prelude_log(PRELUDE_LOG_ERR, "error writing test string to %s: %s.\n", buf, strerror(errno));
-                goto err;
-        }
-
-        ret = get_expected_event(fc, FAMChanged);
-        if ( ret < 0 )
-                goto err;
-
- err:
-        FAMCancelMonitor(fc, &fr);
-        get_expected_event(fc, FAMAcknowledge);
-
-        close(fd);
-        unlink(buf);
-
-        return ret;
-}
-
-
-
-static int initialize_fam(void)
-{
-        int ret;
-
-        if ( fam_initialized != 0 )
-                return fam_initialized;
-
-        fam_initialized = -1;
-
-        ret = FAMOpen(&fc);
-        if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_WARN, "error initializing FAM: %s.\n", FAMErrno ? FamErrlist[FAMErrno] : "unknown");
-                return -1;
-        }
-
-        ret = check_fam_writev_bug(&fc);
-        if ( ret < 0 ) {
-                FAMClose(&fc);
-                prelude_log(PRELUDE_LOG_WARN, "FAM file notification not working: using polling method.\n");
-                return -1;
-        }
-
-        prelude_log(PRELUDE_LOG_DEBUG, "Checking for FAM writev() bug: FAM working nicely, enabling.\n");
-
-        fam_initialized = 1;
-
-        return 0;
-}
-
-
-
-static int fam_setup_monitor(monitor_fd_t *monitor)
-{
-        int ret;
-        const char *filename;
-
-        if ( batch_mode )
-                return 0;
-
-        ret = initialize_fam();
-        if ( ret < 0 )
-                return 0;
-
-        filename = lml_log_source_get_name(monitor->source);
-
-        ret = FAMMonitorFile(&fc, filename, &monitor->fam_request, monitor);
-        if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_WARN, "error creating FAM monitor for %s: %s.\n", filename, FamErrlist[FAMErrno]);
-                return -1;
-        }
-
-        return 0;
-}
-
-
-static int fam_process_event(FAMEvent *event)
-{
-        int ret = 0;
-        monitor_fd_t *monitor = event->userdata;
-
-        switch (event->code) {
-        case FAMCreated:
-        case FAMChanged:
-                if ( ! monitor->fd && monitor_open(monitor) < 0 )
-                        return -1;
-
-        case FAMDeleted:
-                ret = process_file_event(monitor);
-                break;
-
-        case FAMExists:
-        case FAMEndExist:
-                /*
-                 * This happen when a monitor is created.
-                 */
-                return 0;
-
-        default:
-                return -1;
-        }
-
-        return ret;
-}
-
-
-
-
-static int fam_process_queued_events(void)
-{
-        int ret;
-        FAMEvent event;
-
-        while ( FAMPending(&fc) ) {
-                ret = FAMNextEvent(&fc, &event);
-                if ( ret < 0 ) {
-                        prelude_log(PRELUDE_LOG_WARN, "error while getting FAM event: %s.\n", FamErrlist[FAMErrno]);
-                        return -1;
-                }
-
-                fam_process_event(&event);
-        }
-
-        return 0;
-}
-#endif
-
-
-
 int file_server_monitor_file(lml_log_source_t *ls)
 {
         monitor_fd_t *new;
 
-        /*
-         * Don't open the monitor right now,
-         * we want all unread bytes to be processed before activating
-         * FAM notification (if enabled).
-         */
-
         new = monitor_new(ls);
         if ( ! new )
                 return -1;
 
-#if 0
-        ret = monitor_open(new);
-        if ( ret < 0 ) {
-                prelude_log(PRELUDE_LOG_ERR, "couldn't open %s for reading.\n", log_source_get_name(ls));
-                free(new);
-                return -1;
-        }
-#endif
-
         return 0;
 }
 
 
-
-int file_server_wake_up(void)
+int file_server_read_once(void)
 {
         int ret = -1, event;
         monitor_fd_t *monitor;
         prelude_list_t *tmp, *bkp;
 
-        if ( fam_initialized != 1 || batch_mode ) {
-                /*
-                 * try to open inactive fd (file was not existing previously).
-                 */
-                try_reopening_inactive_monitor();
+        prelude_list_for_each_safe(&active_fd_list, tmp, bkp) {
+                monitor = prelude_list_entry(tmp, monitor_fd_t, list);
 
-                prelude_list_for_each_safe(&active_fd_list, tmp, bkp) {
-                        monitor = prelude_list_entry(tmp, monitor_fd_t, list);
-
-                        event = process_file_event(monitor);
-                        if ( event > 0 )
-                                ret = event;
-                }
+                event = check_logfile_data(monitor, &monitor->event.attr);
+                if ( event > 0 )
+                        ret = event;
         }
 
-#ifdef HAVE_FAM
-        else
-                return fam_process_queued_events();
-#endif
-
         return ret;
 }
 
 
 
-
-int file_server_get_event_fd(void)
-{
-#ifdef HAVE_FAM
-        if ( fam_initialized == 1 )
-                return FAMCONNECTION_GETFD(&fc);
-#endif
-
-        return -1;
-}
-
-
-
-
 void file_server_set_max_rotation_time_offset(unsigned int val)
 {
         max_rotation_time_offset = val;
@@ -1184,23 +915,32 @@
 }
 
 
-void file_server_start_monitoring(void)
+int file_server_start_monitoring(void)
 {
-        /*
-         * Initialize everythings once by calling file_server_wake_up().
-         */
-        if ( fam_initialized == 1 )
-                try_reopening_inactive_monitor();
+        monitor_fd_t *monitor;
+        prelude_list_t *tmp, *bkp;
+        int cnt = 0, failed_cnt = 0, ret;
+
+        prelude_list_for_each_safe(&inactive_fd_list, tmp, bkp) {
+                monitor = prelude_list_entry(tmp, monitor_fd_t, list);
+
+                cnt++;
+
+                ret = monitor_open(monitor);
+                if ( ret < 0 )
+                        failed_cnt++;
+        }
+
+        return (failed_cnt < cnt) ? 0 : -1;
 }
 
 
 void file_server_set_metadata_flags(file_server_metadata_flags_t flags)
 {
+        if ( ! (flags & (FILE_SERVER_METADATA_FLAGS_HEAD|
+                         FILE_SERVER_METADATA_FLAGS_LAST|
+                         FILE_SERVER_METADATA_FLAGS_TAIL)) )
+                flags |= FILE_SERVER_METADATA_FLAGS_LAST;
+
         metadata_flags = flags;
 }
-
-
-void file_server_set_batch_mode(void)
-{
-        batch_mode = 1;
-}

Modified: prelude-lml/trunk/src/include/file-server.h
===================================================================
--- prelude-lml/trunk/src/include/file-server.h	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/include/file-server.h	2008-10-15 13:00:25 UTC (rev 11064)
@@ -30,18 +30,13 @@
 } file_server_metadata_flags_t;
 
 
-
-int file_server_get_event_fd(void);
-
-void file_server_set_batch_mode(void);
-
 void file_server_set_metadata_flags(file_server_metadata_flags_t flags);
 
-int file_server_wake_up(void);
+int file_server_read_once(void);
 
 int file_server_monitor_file(lml_log_source_t *ls);
 
-void file_server_start_monitoring(void);
+int file_server_start_monitoring(void);
 
 unsigned int file_server_get_max_rotation_time_offset(void);
 

Modified: prelude-lml/trunk/src/include/lml-options.h
===================================================================
--- prelude-lml/trunk/src/include/lml-options.h	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/include/lml-options.h	2008-10-15 13:00:25 UTC (rev 11064)
@@ -6,7 +6,7 @@
 * This file is part of the Prelude-LML program.
 *
 * 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 
+* it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
@@ -41,10 +41,11 @@
         prelude_bool_t dry_run;
         prelude_bool_t ignore_metadata;
         prelude_bool_t no_resolve;
+        prelude_bool_t daemon_mode;
 
         size_t udp_nserver;
         udp_server_t **udp_server;
-        
+
         prelude_io_t *text_output_fd;
         unsigned long alert_count;
         unsigned long line_processed;

Modified: prelude-lml/trunk/src/lml-options.c
===================================================================
--- prelude-lml/trunk/src/lml-options.c	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/lml-options.c	2008-10-15 13:00:25 UTC (rev 11064)
@@ -57,7 +57,6 @@
 
 
 lml_config_t config;
-static prelude_bool_t have_file = FALSE;
 static const char *config_file = PRELUDE_LML_CONF;
 
 
@@ -122,7 +121,6 @@
 static int set_batch_mode(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context)
 {
         config.batch_mode = TRUE;
-        file_server_set_batch_mode();
         return 0;
 }
 
@@ -247,12 +245,9 @@
 
 static int set_daemon_mode(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context)
 {
-        prelude_daemonize(config.pidfile);
-        if ( config.pidfile )
-                free(config.pidfile);
-
         prelude_log_set_flags(prelude_log_get_flags()|PRELUDE_LOG_FLAGS_QUIET|PRELUDE_LOG_FLAGS_SYSLOG);
 
+        config.daemon_mode = TRUE;
         return 0;
 }
 
@@ -316,81 +311,68 @@
 }
 
 
-static int check_file_access(const char *filename)
+static int glob_errfunc_cb(const char *epath, int eerrno)
 {
-        int ret;
-        struct stat st;
+        prelude_log(PRELUDE_LOG_WARN, "error with '%s': %s.\n", epath, strerror(eerrno));
+        return 0;
+}
 
-        ret = stat(filename, &st);
-        if ( ret < 0 ) {
-                if ( errno == ENOENT )
-                        prelude_log(PRELUDE_LOG_WARN, "%s does not exist.\n", filename);
 
-                else if ( errno == EACCES )
-                        goto out;
+static prelude_bool_t isglob(const char *pattern)
+{
+        int i;
+        const char *ptr;
+        char chlist[] = { '*', '?', '[', '~' };
 
-                else prelude_log(PRELUDE_LOG_WARN, "could not stat %s: %s.\n", filename, strerror(errno));
+        for ( i = 0; i < sizeof(chlist) / sizeof(*chlist); i++ ) {
+                ptr = strchr(pattern, chlist[i]);
+                if ( ! ptr )
+                        continue;
 
-                return -1;
+                if ( ptr == pattern || *(ptr - 1) != '\\' )
+                        return TRUE;
         }
 
-        if ( config.wanted_uid == 0 )
-                return 0;
+        return FALSE;
+}
 
-        if ( st.st_uid == config.wanted_uid && st.st_mode & S_IRUSR )
-                return 0;
 
-        if ( st.st_gid == config.wanted_gid && st.st_mode & S_IRGRP )
-                return 0;
+static int add_file(void *context, const char *filename)
+{
+        int ret;
+        lml_log_source_t *ls;
 
-        if ( st.st_mode & S_IROTH )
+        ret = lml_log_source_new(&ls, context, filename);
+        if ( ret < 0 )
+                return -1;
+
+        else if ( ret == 1 )
                 return 0;
 
- out:
-        prelude_log(PRELUDE_LOG_WARN, "%s is not available for reading to uid %d/gid %d.\n",
-                    filename, config.wanted_uid, config.wanted_gid);
-
-        return -1;
+        return file_server_monitor_file(ls);
 }
 
 
-static int glob_errfunc_cb(const char *epath, int eerrno)
-{
-        prelude_log(PRELUDE_LOG_WARN, "error with '%s': %s.\n", epath, strerror(eerrno));
-        return 0;
-}
-
-
 static int get_file_from_pattern(void *context, const char *pattern)
 {
         int ret;
         size_t i;
         glob_t gl;
-        lml_log_source_t *ls;
 
-        ret = glob(pattern, GLOB_NOCHECK | GLOB_TILDE, glob_errfunc_cb, &gl);
+        ret = glob(pattern, GLOB_TILDE, glob_errfunc_cb, &gl);
         if ( ret != 0 ) {
-                prelude_log(PRELUDE_LOG_ERR, "glob failed: %s.\n", strerror(errno));
+                if ( ret == GLOB_NOMATCH )
+                        prelude_log(PRELUDE_LOG_WARN, "%s: not found, no monitoring will occur.\n", pattern);
+                else
+                        prelude_log(PRELUDE_LOG_ERR, "%s glob failed: %s.\n", pattern, strerror(errno));
+
                 return ret;
         }
 
         for ( i = 0; i < gl.gl_pathc; i++ ) {
-                ret = check_file_access(gl.gl_pathv[i]);
+                ret = add_file(context, gl.gl_pathv[i]);
                 if ( ret < 0 )
-                        continue; /* ignore error */
-
-                ret = lml_log_source_new(&ls, context, gl.gl_pathv[i]);
-                if ( ret < 0 )
                         break;
-
-                else if ( ret == 1 )
-                        continue;
-
-                ret = file_server_monitor_file(ls);
-                if ( ret < 0 )
-                        break;
-
-                have_file = TRUE;
         }
 
         globfree(&gl);
@@ -399,28 +381,21 @@
 }
 
 
+
 static int set_file(prelude_option_t *opt, const char *arg, prelude_string_t *err, void *context)
 {
         int ret;
-        lml_log_source_t *ls;
 
-        if ( *arg != '-' ) {
-                ret = get_file_from_pattern(context, arg);
-                if ( ret < 0 )
-                        return 0; /* ignore error */
-        } else {
-                ret = lml_log_source_new(&ls, context, arg);
-                if ( ret < 0 )
-                        return prelude_error_from_errno(errno);
+        if ( strcmp(arg, "-") == 0 )
+                return add_file(context, arg);
 
-                if ( ret == 1 )
-                        return 0;
+        else if ( ! isglob(arg) )
+                return add_file(context, arg);
 
-                ret = file_server_monitor_file(ls);
+        else {
+                ret = get_file_from_pattern(context, arg);
                 if ( ret < 0 )
-                        return ret;
-
-                have_file = TRUE;
+                        return 0; /* ignore error */
         }
 
         return 0;
@@ -709,10 +684,6 @@
                 return -1;
         }
 
-        if ( ! have_file && ! config.udp_nserver ) {
-                prelude_log(PRELUDE_LOG_WARN, "No file or UDP server available for monitoring: terminating.\n");
-                return -1;
-        }
 
 #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
         ret = drop_privilege();

Modified: prelude-lml/trunk/src/prelude-lml.c
===================================================================
--- prelude-lml/trunk/src/prelude-lml.c	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/prelude-lml.c	2008-10-15 13:00:25 UTC (rev 11064)
@@ -48,9 +48,12 @@
 # endif
 #endif
 
+#include "ev.h"
+
 #include <libprelude/prelude.h>
 #include <libprelude/prelude-log.h>
 #include <libprelude/prelude-timer.h>
+#include <libprelude/daemonize.h>
 
 #include "config.h"
 
@@ -83,6 +86,7 @@
 static char **global_argv;
 static prelude_option_t *lml_root_optlist;
 static volatile sig_atomic_t got_signal = 0;
+static ev_async ev_interrupt;
 
 
 
@@ -97,10 +101,10 @@
 }
 
 
-
 static RETSIGTYPE sig_handler(int signum)
 {
         got_signal = signum;
+        ev_async_send(EV_DEFAULT_ &ev_interrupt);
 }
 
 
@@ -198,18 +202,32 @@
 }
 
 
+static void libev_timer_cb(struct ev_timer *w, int revents)
+{
+        prelude_timer_wake_up();
+}
 
+
+static void libev_udp_cb(struct ev_io *w, int revents)
+{
+        udp_server_process_event(w->data);
+}
+
+
+static void libev_interrupt_cb(EV_P_ ev_async *w, int revents)
+{
+        _lml_handle_signal_if_needed();
+}
+
+
 static void regex_match_cb(void *plugin, void *data)
 {
         struct regex_data *rdata = data;
-
         log_plugin_run(plugin, rdata->log_source, rdata->log_entry);
 }
 
 
 
-
-
 /**
  * lml_dispatch_log:
  * @list: List of regex.
@@ -242,75 +260,25 @@
 }
 
 
-
 static void wait_for_event(void)
 {
-        int ret;
         size_t i;
-        fd_set fds;
-        struct timeval tv, lstart, end;
-        int file_event_fd, udp_event_fd, max = 0;
+        int udp_event_fd;
+        ev_io events[config.udp_nserver];
 
-        FD_ZERO(&fds);
+        ev_async_init(&ev_interrupt, libev_interrupt_cb);
+        ev_async_start(&ev_interrupt);
 
-        file_event_fd = file_server_get_event_fd();
-        if ( file_event_fd >= 0 ) {
-                max = file_event_fd;
-                FD_SET(file_event_fd, &fds);
-        }
-
         for ( i = 0; i < config.udp_nserver; i++ ) {
                 udp_event_fd = udp_server_get_event_fd(config.udp_server[i]);
 
-                FD_SET(udp_event_fd, &fds);
-                max = MAX(max, udp_event_fd);
-        }
+                ev_io_init(&events[i], libev_udp_cb, udp_event_fd, EV_READ);
+                events[i].data = config.udp_server[i];
 
-        gettimeofday(&start, NULL);
-        gettimeofday(&lstart, NULL);
-
-        while ( 1 ) {
-                _lml_handle_signal_if_needed();
-
-                tv.tv_sec = 1;
-                tv.tv_usec = 0;
-
-                ret = select(max + 1, &fds, NULL, NULL, &tv);
-                if ( ret < 0 ) {
-                        if ( errno == EINTR )
-                                continue;
-
-                        prelude_log(PRELUDE_LOG_ERR, "select returned an error: %s.\n", strerror(errno));
-                        break;
-                }
-
-                gettimeofday(&end, NULL);
-
-                if ( ret == 0 || end.tv_sec - lstart.tv_sec >= 1 ) {
-                        gettimeofday(&lstart, NULL);
-                        prelude_timer_wake_up();
-
-                        if ( file_event_fd < 0 )
-                                file_server_wake_up();
-                }
-
-                for ( i = 0; i < config.udp_nserver; i++ ) {
-                        udp_event_fd = udp_server_get_event_fd(config.udp_server[i]);
-
-                        if ( FD_ISSET(udp_event_fd, &fds) )
-                                udp_server_process_event(config.udp_server[i]);
-                        else
-                                FD_SET(udp_event_fd, &fds);
-                }
-
-                if ( file_event_fd < 0 )
-                        continue;
-
-                if ( FD_ISSET(file_event_fd, &fds) )
-                        file_server_wake_up();
-                else
-                        FD_SET(file_event_fd, &fds);
+                ev_io_start(&events[i]);
         }
+
+        ev_loop(0);
 }
 
 
@@ -318,10 +286,16 @@
 int main(int argc, char **argv)
 {
         int ret;
+        ev_timer evt;
         struct timeval end;
         struct sigaction action;
 
         /*
+         * Initialize libev.
+         */
+        ev_default_loop(EVFLAG_AUTO);
+
+        /*
          * make sure we ignore sighup until acceptable.
          */
 #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
@@ -373,29 +347,42 @@
         sigaction(SIGHUP, &action, NULL);
 #endif
 
-        file_server_start_monitoring();
+        ret = file_server_start_monitoring();
+        if ( ret < 0 && ! config.udp_nserver ) {
+                prelude_log(PRELUDE_LOG_WARN, "No file or UDP server available for monitoring: terminating.\n");
+                return -1;
+        }
 
+        if ( config.daemon_mode ) {
+                prelude_daemonize(config.pidfile);
+                if ( config.pidfile )
+                        free(config.pidfile);
+
+                ev_default_fork();
+        }
+
+        ev_timer_init(&evt, libev_timer_cb, 1, 1);
+        ev_timer_start(&evt);
+
         /*
+         * Whether we are using batch-mode or file notification, we need
+         * to process the currently un-processed entry.
+         */
+        gettimeofday(&start, NULL);
+
+        do {
+                ret = file_server_read_once();
+                prelude_timer_wake_up();
+        } while ( ret > 0 );
+
+        /*
          * if either FAM or UDP server is enabled, we use polling to know
          * if there are data available for reading. if batch_mode is set,
          * then we revert to reading every data at once.
          */
-        if ( (config.udp_nserver || file_server_get_event_fd() > 0) && ! config.batch_mode )
+        if ( ! config.batch_mode )
                 wait_for_event();
         else {
-                gettimeofday(&start, NULL);
-
-                do {
-                        _lml_handle_signal_if_needed();
-                        ret = file_server_wake_up();
-
-                        if ( ! config.batch_mode )
-                                sleep(1);
-
-                        prelude_timer_wake_up();
-
-                } while ( ! config.batch_mode || ret > 0 );
-
                 gettimeofday(&end, NULL);
 
                 /*

Modified: prelude-lml/trunk/src/regex.c
===================================================================
--- prelude-lml/trunk/src/regex.c	2008-10-13 13:24:07 UTC (rev 11063)
+++ prelude-lml/trunk/src/regex.c	2008-10-15 13:00:25 UTC (rev 11064)
@@ -140,8 +140,8 @@
         }
 
         plugin = prelude_plugin_instance_get_plugin(entry->plugin);
-        prelude_log(PRELUDE_LOG_INFO, "Monitoring %s through %s[%s]\n",
-                    source, plugin->name, prelude_plugin_instance_get_name(entry->plugin));
+        prelude_log_debug(1, "Will route %s data through %s[%s]\n",
+                          source, plugin->name, prelude_plugin_instance_get_name(entry->plugin));
 
         prelude_log(PRELUDE_LOG_DEBUG, "[REGEX] rule found: plugin: %s - pattern: %s\n", rt->plugin, rt->regex);
 

_______________________________________________
Prelude-cvslog site list
[email protected]
http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.