diff -x '*.po' -d -urpN abrt.1/abrt.spec.in abrt.2/abrt.spec.in
--- abrt.1/abrt.spec.in	2012-02-28 14:29:11.000000000 +0100
+++ abrt.2/abrt.spec.in	2012-03-14 03:14:52.446107757 +0100
@@ -505,6 +505,7 @@ gtk-update-icon-cache %{_datadir}/icons/
 %else
 %{_initrddir}/abrt-oops
 %endif
+%{_bindir}/abrt-watch-log
 %{_bindir}/abrt-dump-oops
 %{_bindir}/abrt-action-analyze-oops
 %{_mandir}/man1/abrt-action-analyze-oops.1*
diff -x '*.po' -d -urpN abrt.1/examples/not_oops1.right abrt.2/examples/not_oops1.right
--- abrt.1/examples/not_oops1.right	2011-10-27 19:11:55.000000000 +0200
+++ abrt.2/examples/not_oops1.right	2012-03-14 12:52:44.784907917 +0100
@@ -1 +0,0 @@
-abrt-dump-oops: Found oopses: 0
diff -x '*.po' -d -urpN abrt.1/examples/not_oops2.right abrt.2/examples/not_oops2.right
--- abrt.1/examples/not_oops2.right	2011-10-27 19:11:55.000000000 +0200
+++ abrt.2/examples/not_oops2.right	2012-03-14 12:52:49.088877135 +0100
@@ -1 +0,0 @@
-abrt-dump-oops: Found oopses: 0
diff -x '*.po' -d -urpN abrt.1/examples/not_oops3.right abrt.2/examples/not_oops3.right
--- abrt.1/examples/not_oops3.right	2011-10-27 19:11:55.000000000 +0200
+++ abrt.2/examples/not_oops3.right	2012-03-14 12:52:52.861850154 +0100
@@ -1 +0,0 @@
-abrt-dump-oops: Found oopses: 0
diff -x '*.po' -d -urpN abrt.1/examples/test.sh abrt.2/examples/test.sh
--- abrt.1/examples/test.sh	2011-10-27 19:11:55.000000000 +0200
+++ abrt.2/examples/test.sh	2012-03-14 13:19:49.482350537 +0100
@@ -1,7 +1,10 @@
 for f in *.test; do
         b="${f%%.test}"
-        abrt-dump-oops -o "$f" >"$b".out 2>&1
+        abrt-dump-oops -o <"$f" >"$b".out 2>&1
         if diff -u "$b".right "$b".out >"$b".diff 2>&1; then
+                echo "Tested $f: ok"
                 rm "$b".out "$b".diff
+        else
+                echo "Tested $f: BAD"
         fi
 done
diff -x '*.po' -d -urpN abrt.1/.gitignore abrt.2/.gitignore
--- abrt.1/.gitignore	2012-02-28 14:29:11.000000000 +0100
+++ abrt.2/.gitignore	2012-03-14 03:15:04.891070662 +0100
@@ -23,6 +23,7 @@ src/plugins/abrt-action-analyze-vmcore
 src/plugins/abrt-action-generate-backtrace
 src/plugins/abrt-action-install-debuginfo-to-abrt-cache
 src/plugins/abrt-action-trim-files
+src/plugins/abrt-watch-log
 src/plugins/abrt-dump-oops
 src/plugins/abrt-dedup-client
 src/plugins/abrt-retrace-client
diff -x '*.po' -d -urpN abrt.1/init-scripts/abrt-oops abrt.2/init-scripts/abrt-oops
--- abrt.1/init-scripts/abrt-oops	2011-10-27 19:11:55.000000000 +0200
+++ abrt.2/init-scripts/abrt-oops	2012-03-14 12:40:03.241409684 +0100
@@ -33,14 +33,19 @@ check() {
 
 start() {
 	check
-	killall abrt-dump-oops 2>/dev/null
-	setsid abrt-dump-oops -rwxD /var/log/messages </dev/null >/dev/null 2>&1 &
+#FIXME: need to kill only abrt-watch-log which watches /var/log/messages!
+	killall abrt-watch-log 2>/dev/null
+	# Scan dmesg
+	dmesg | abrt-dump-oops -xD
+	# Watch and scan /var/log/messages
+	setsid abrt-watch-log -w /var/log/messages -- abrt-dump-oops -xD </dev/null >/dev/null 2>&1 &
 	$dry_run || touch -- "$LOCK"
 	return $RETVAL
 }
 
 stop() {
 	check
+#FIXME: need to kill only abrt-watch-log which watches /var/log/messages!
 	killall abrt-dump-oops
 	$dry_run || rm -f -- "$LOCK"
 	return $RETVAL
diff -x '*.po' -d -urpN abrt.1/init-scripts/abrt-oops.service abrt.2/init-scripts/abrt-oops.service
--- abrt.1/init-scripts/abrt-oops.service	2011-11-11 13:54:02.000000000 +0100
+++ abrt.2/init-scripts/abrt-oops.service	2012-03-14 13:32:11.168794069 +0100
@@ -4,7 +4,7 @@ After=abrtd.service
 Requires=abrtd.service
 
 [Service]
-ExecStart=/usr/bin/abrt-dump-oops -rwxD /var/log/messages
+ExecStart=/usr/bin/abrt-watch-log -w /var/log/messages -- /usr/bin/abrt-dump-oops -xD
 
 [Install]
 WantedBy=multi-user.target
diff -x '*.po' -d -urpN abrt.1/po/POTFILES.in abrt.2/po/POTFILES.in
--- abrt.1/po/POTFILES.in	2012-02-16 10:09:08.000000000 +0100
+++ abrt.2/po/POTFILES.in	2012-03-14 03:24:28.105323391 +0100
@@ -21,6 +21,7 @@ src/plugins/abrt-action-generate-core-ba
 src/plugins/abrt-action-install-debuginfo
 src/plugins/abrt-action-trim-files.c
 src/plugins/abrt-dedup-client.c
+src/plugins/abrt-watch-log.c
 src/plugins/abrt-dump-oops.c
 src/plugins/abrt-retrace-client.c
 src/plugins/analyze_LocalGDB.xml.in
diff -x '*.po' -d -urpN abrt.1/src/plugins/abrt-action-analyze-vmcore.in abrt.2/src/plugins/abrt-action-analyze-vmcore.in
--- abrt.1/src/plugins/abrt-action-analyze-vmcore.in	2012-02-28 14:29:11.000000000 +0100
+++ abrt.2/src/plugins/abrt-action-analyze-vmcore.in	2012-03-14 13:18:50.141654159 +0100
@@ -123,5 +123,6 @@ if __name__ == "__main__":
     out, err = crash.communicate(input="log")
     log_file.close()
     backtrace_file = open("backtrace", "w")
-    dump_oops = Popen(["abrt-dump-oops", "-o", "kernel_log"], stdout=backtrace_file, bufsize=-1)
+    kernel_log_file = open("kernel_log", "r")
+    dump_oops = Popen(["abrt-dump-oops", "-o"], stdin=kernel_log_file, stdout=backtrace_file, bufsize=-1)
     backtrace_file.close()
diff -x '*.po' -d -urpN abrt.1/src/plugins/abrt-dump-oops.c abrt.2/src/plugins/abrt-dump-oops.c
--- abrt.1/src/plugins/abrt-dump-oops.c	1970-01-01 01:00:00.000000000 +0100
+++ abrt.2/src/plugins/abrt-dump-oops.c	2012-03-14 12:46:15.173708053 +0100
@@ -0,0 +1,277 @@
+/*
+    Copyright (C) 2011  ABRT team
+    Copyright (C) 2011  RedHat Inc
+
+    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.
+
+    Authors:
+       Anton Arapov <anton@redhat.com>
+       Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <syslog.h>
+#include "libabrt.h"
+
+
+static bool world_readable_dump = false;
+static const char *debug_dumps_dir = ".";
+
+#define MAX_SCAN_BLOCK  (4*1024*1024)
+#define READ_AHEAD          (10*1024)
+
+static void scan_syslog_file(GList **oops_list, int fd)
+{
+    struct stat st;
+    struct stat *statbuf = &st;
+
+    /* Try to not allocate an absurd amount of memory */
+    int sz = MAX_SCAN_BLOCK - READ_AHEAD;
+    /* If it's a real file, estimate size after cur pos */
+    off_t cur_pos = lseek(fd, 0, SEEK_CUR);
+    if (cur_pos >= 0 && fstat(fd, statbuf) == 0 && S_ISREG(statbuf->st_mode))
+    {
+        off_t size_to_read = statbuf->st_size - cur_pos;
+        if (size_to_read >= 0 && sz > size_to_read)
+            sz = size_to_read;
+    }
+
+    /*
+     * In theory we have a race here, since someone can spew
+     * to /var/log/messages before we read it in...
+     * We try to deal with it by reading READ_AHEAD extra.
+     */
+    sz += READ_AHEAD;
+    char *buffer = xzalloc(sz);
+
+    for (;;)
+    {
+        int r = full_read(fd, buffer, sz-1);
+        if (r <= 0)
+            break;
+        VERB3 log("Read %u bytes", r);
+        koops_extract_oopses(oops_list, buffer, r);
+//TODO: rewind to last newline?
+    }
+
+    free(buffer);
+}
+
+/* returns number of errors */
+static unsigned save_oops_to_dump_dir(GList *oops_list, unsigned oops_cnt)
+{
+    unsigned countdown = 16; /* do not report hundreds of oopses */
+    unsigned idx = oops_cnt;
+
+    VERB1 log("Saving %u oopses as dump dirs", idx >= countdown ? countdown-1 : idx);
+
+    char *cmdline_str = NULL;
+    FILE *cmdline_fp = fopen("/proc/cmdline", "r");
+    if (cmdline_fp)
+    {
+        cmdline_str = xmalloc_fgetline(cmdline_fp);
+        fclose(cmdline_fp);
+    }
+
+    time_t t = time(NULL);
+    const char *iso_date = iso_date_string(&t);
+    /* dump should be readable by all if we're run with -x */
+    uid_t my_euid = (uid_t)-1L;
+    mode_t mode = 0644;
+    /* and readable only for the owner otherwise */
+    if (!world_readable_dump)
+    {
+        mode = 0640;
+        my_euid = geteuid();
+    }
+
+    pid_t my_pid = getpid();
+    unsigned errors = 0;
+    while (idx != 0 && --countdown != 0)
+    {
+        char *first_line = (char*)g_list_nth_data(oops_list, --idx);
+        char *second_line = (char*)strchr(first_line, '\n'); /* never NULL */
+        *second_line++ = '\0';
+
+        struct dump_dir *dd;
+        {
+            char base[sizeof("oops-YYYY-MM-DD-hh:mm:ss-%lu-%lu") + 2 * sizeof(long)*3];
+            sprintf(base, "oops-%s-%lu-%lu", iso_date, (long)my_pid, (long)idx);
+            char *path = concat_path_file(debug_dumps_dir, base);
+            dd = dd_create(path, /*uid:*/ my_euid, mode);
+            free(path);
+        }
+
+        if (dd)
+        {
+            dd_create_basic_files(dd, /*uid:*/ my_euid);
+            dd_save_text(dd, "abrt_version", VERSION);
+            dd_save_text(dd, FILENAME_ANALYZER, "Kerneloops");
+            dd_save_text(dd, FILENAME_KERNEL, first_line);
+            if (cmdline_str)
+                dd_save_text(dd, FILENAME_CMDLINE, cmdline_str);
+            dd_save_text(dd, FILENAME_BACKTRACE, second_line);
+
+            /* check if trace doesn't have line: 'Your BIOS is broken' */
+            char *broken_bios = strstr(second_line, "Your BIOS is broken");
+            if (broken_bios)
+                dd_save_text(dd, FILENAME_NOT_REPORTABLE, "Your BIOS is broken");
+
+            char *tainted_short = kernel_tainted_short(second_line);
+            if (tainted_short && !broken_bios)
+            {
+                VERB1 log("Kernel is tainted '%s'", tainted_short);
+                dd_save_text(dd, FILENAME_TAINTED_SHORT, tainted_short);
+                const char *fmt = _("A kernel problem occurred, but your kernel has been"
+                             "tainted (flags:%s). Kernel maintainers are unable to"
+                             "diagnose tainted reports.");
+
+                char *reason = xasprintf(fmt, tainted_short);
+
+                dd_save_text(dd, FILENAME_NOT_REPORTABLE, reason);
+                free(reason);
+            }
+// TODO: add "Kernel oops: " prefix, so that all oopses have recognizable FILENAME_REASON?
+// kernel oops 1st line may look quite puzzling otherwise...
+            strchrnul(second_line, '\n')[0] = '\0';
+            dd_save_text(dd, FILENAME_REASON, second_line);
+
+/*
+            GList *tainted_long = kernel_tainted_long(tainted);
+
+            struct strbuf *tnt_long = strbuf_new();
+            for (GList *li = tainted_long; li; li = li->next)
+                strbuf_append_strf(tnt_long, "%s\n", (char*) li->data);
+
+            dd_save_text(dd, FILENAME_TAINTED, tainted_str);
+            dd_save_text(dd, FILENAME_TAINTED_SHORT, tainted_short);
+            dd_save_text(dd, FILENAME_TAINTED_LONG, tnt_long->buf);
+            strbuf_free(tnt_long);
+            list_free_with_free(tainted_long);
+*/
+            dd_close(dd);
+        }
+        else
+            errors++;
+    }
+
+    free(cmdline_str);
+
+    return errors;
+}
+
+int main(int argc, char **argv)
+{
+    /* I18n */
+    setlocale(LC_ALL, "");
+#if ENABLE_NLS
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+
+    abrt_init(argv);
+
+    /* Can't keep these strings/structs static: _() doesn't support that */
+    const char *program_usage_string = _(
+        "& [-vsox] [-d DIR]/[-D]\n"
+        "\n"
+        "Extract oops from standard input"
+    );
+    enum {
+        OPT_v = 1 << 0,
+        OPT_s = 1 << 1,
+        OPT_o = 1 << 2,
+        OPT_d = 1 << 3,
+        OPT_D = 1 << 4,
+        OPT_x = 1 << 5,
+    };
+    /* Keep enum above and order of options below in sync! */
+    struct options program_options[] = {
+        OPT__VERBOSE(&g_verbose),
+        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
+        OPT_BOOL(  'o', NULL, NULL, _("Print found oopses on standard output")),
+        /* oopses don't contain any sensitive info, and even
+         * the old koops app was showing the oopses to all users
+         */
+        OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create ABRT dump in DIR for every oops found")),
+        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
+        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
+        OPT_END()
+    };
+    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+    if ((opts & OPT_d) && (opts & OPT_D))
+        show_usage_and_die(program_usage_string, program_options);
+
+    export_abrt_envvars(0);
+
+    msg_prefix = g_progname;
+    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
+    {
+        openlog(msg_prefix, 0, LOG_DAEMON);
+        logmode = LOGMODE_SYSLOG;
+    }
+
+//    argv += optind;
+
+    world_readable_dump = (opts & OPT_x);
+    unsigned errors = 0;
+    GList *oops_list = NULL;
+    scan_syslog_file(&oops_list, STDIN_FILENO);
+
+    int oops_cnt = g_list_length(oops_list);
+    if (oops_cnt != 0)
+    {
+        log("Found oopses: %d", oops_cnt);
+        if (opts & OPT_o)
+        {
+            int i = 0;
+            while (i < oops_cnt)
+            {
+                char *kernel_bt = (char*)g_list_nth_data(oops_list, i++);
+                char *tainted_short = kernel_tainted_short(kernel_bt);
+                if (tainted_short)
+                    log("Kernel is tainted '%s'", tainted_short);
+
+                free(tainted_short);
+                printf("\nVersion: %s", kernel_bt);
+            }
+        }
+        if (opts & (OPT_d|OPT_D))
+        {
+            if (opts & OPT_D)
+            {
+                load_abrt_conf();
+                debug_dumps_dir = g_settings_dump_location;
+            }
+
+            log("Creating dump directories");
+            errors = save_oops_to_dump_dir(oops_list, oops_cnt);
+            if (errors)
+                log("%d errors while dumping oopses", errors);
+            /*
+             * This marker in syslog file prevents us from
+             * re-parsing old oopses. The only problem is that we
+             * can't be sure here that the file we are watching
+             * is the same file where syslog(xxx) stuff ends up.
+             */
+            syslog(LOG_WARNING,
+                    "Reported %u kernel oopses to Abrt",
+                    oops_cnt
+            );
+
+//            if (opts & OPT_D)
+//                free_abrt_conf_data();
+        }
+    }
+//    list_free_with_free(oops_list);
+//    oops_list = NULL;
+
+    return errors;
+}
diff -x '*.po' -d -urpN abrt.1/src/plugins/abrt-watch-log.c abrt.2/src/plugins/abrt-watch-log.c
--- abrt.1/src/plugins/abrt-watch-log.c	1970-01-01 01:00:00.000000000 +0100
+++ abrt.2/src/plugins/abrt-watch-log.c	2012-03-14 13:12:27.424596150 +0100
@@ -0,0 +1,212 @@
+/*
+    Copyright (C) 2011  ABRT team
+    Copyright (C) 2011  RedHat Inc
+
+    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.
+
+    Authors:
+       Anton Arapov <anton@redhat.com>
+       Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <syslog.h>
+#include <sys/inotify.h>
+#include "libabrt.h"
+
+static void run_scanner_prog(int fd, struct stat *statbuf, char **prog)
+{
+    /* fstat(fd, &statbuf) was just done by caller */
+
+    off_t cur_pos = lseek(fd, 0, SEEK_CUR);
+    if (statbuf->st_size <= cur_pos)
+    {
+        /* If file was truncated, treat it as a new file.
+         * (changing inode# causes caller to think that file was closed or renamed)
+         */
+        if (statbuf->st_size < cur_pos)
+            statbuf->st_ino++;
+        return; /* we are at EOF, nothing to do */
+    }
+
+    VERB3 log("File grew by %llu bytes, from %llu to %llu",
+        (long long)(statbuf->st_size - cur_pos),
+        (long long)(cur_pos),
+        (long long)(statbuf->st_size));
+
+    pid_t pid = vfork();
+    if (pid < 0)
+        perror_msg_and_die("vfork");
+    if (pid == 0)
+    {
+        xmove_fd(fd, STDIN_FILENO);
+        execvp(prog[0], prog);
+        perror_msg_and_die("Can't execute '%s'", prog[0]);
+    }
+
+    safe_waitpid(pid, NULL, 0);
+
+//TODO: check fd's position, and move to end if wasn't changed.
+}
+
+int main(int argc, char **argv)
+{
+    /* I18n */
+    setlocale(LC_ALL, "");
+#if ENABLE_NLS
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+
+    abrt_init(argv);
+
+    /* Can't keep these strings/structs static: _() doesn't support that */
+    const char *program_usage_string = _(
+        "& [-vsw] FILE PROG [ARGS]\n"
+        "\n"
+        "Watch log file FILE, run PROG when it grows or is replaced"
+    );
+    enum {
+        OPT_v = 1 << 0,
+        OPT_s = 1 << 1,
+        OPT_w = 1 << 2,
+    };
+    /* Keep enum above and order of options below in sync! */
+    struct options program_options[] = {
+        OPT__VERBOSE(&g_verbose),
+        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
+        OPT_BOOL(  'w', NULL, NULL, _("Do not exit, watch FILE for changes")),
+        OPT_END()
+    };
+    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+    export_abrt_envvars(0);
+
+    msg_prefix = g_progname;
+    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
+    {
+        openlog(msg_prefix, 0, LOG_DAEMON);
+        logmode = LOGMODE_SYSLOG;
+    }
+
+    argv += optind;
+    if (!argv[0] || !argv[1])
+        show_usage_and_die(program_usage_string, program_options);
+
+    const char *filename = *argv++;
+
+    int inotify_fd = -1;
+    if (opts & OPT_w)
+    {
+        inotify_fd = inotify_init();
+        if (inotify_fd == -1)
+            perror_msg_and_die("inotify_init failed");
+        close_on_exec_on(inotify_fd);
+    }
+
+    struct stat statbuf;
+    int file_fd = -1;
+    int wd = -1;
+
+    while (1) /* loops only if -w */
+    {
+        /* If file is already opened, scan it from current pos */
+        if (file_fd >= 0)
+        {
+            memset(&statbuf, 0, sizeof(statbuf));
+            fstat(file_fd, &statbuf);
+            run_scanner_prog(file_fd, &statbuf, argv);
+
+            /* Was file deleted or replaced? */
+            ino_t fd_ino = statbuf.st_ino;
+            if (stat(filename, &statbuf) != 0 || statbuf.st_ino != fd_ino) /* yes */
+            {
+                VERB2 log("Inode# changed, closing fd");
+                close(file_fd);
+                if (wd >= 0)
+                    inotify_rm_watch(inotify_fd, wd);
+                file_fd = -1;
+                wd = -1;
+            }
+        }
+
+        /* If file isn't opened, try to open it and scan */
+        if (file_fd < 0)
+        {
+            file_fd = open(filename, O_RDONLY);
+            if (file_fd < 0)
+            {
+                if (!(opts & OPT_w))
+                    perror_msg_and_die("Can't open '%s'", filename);
+                /* with -w, we ignore open errors */
+            }
+            else
+            {
+                VERB2 log("Opened '%s'", filename);
+                /* For -w case, if we don't have inotify watch yet, open one */
+                if ((opts & OPT_w) && wd < 0)
+                {
+                    wd = inotify_add_watch(inotify_fd, filename, IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF);
+                    if (wd < 0)
+                        perror_msg("inotify_add_watch failed on '%s'", filename);
+                    else
+                        VERB2 log("Added inotify watch for '%s'", filename);
+                }
+                if (fstat(file_fd, &statbuf) == 0)
+                {
+                    /* If file is large, skip the beginning.
+                     * IOW: ignore old log messages because they are unlikely
+                     * to have sufficiently recent data to be useful.
+                     */
+#define MAX_SCAN_BLOCK  (4*1024*1024)
+#define READ_AHEAD          (10*1024)
+                    if (statbuf.st_size > (MAX_SCAN_BLOCK - READ_AHEAD))
+                        lseek(file_fd, statbuf.st_size - (MAX_SCAN_BLOCK - READ_AHEAD), SEEK_SET);
+                    /* Note that statbuf is filled by fstat by now,
+                     * run_scanner_prog needs that
+                     */
+                    run_scanner_prog(file_fd, &statbuf, argv);
+                }
+            }
+        }
+
+        /* Done if no -w */
+        if (!(opts & OPT_w))
+            break;
+
+        /* Even if log file grows all the time, say, a new line every 5 ms,
+         * we don't want to scan it all the time. Sleep a bit and let it grow
+         * in bigger increments.
+         * Sleep longer if file does not exist.
+         */
+        sleep(file_fd >= 0 ? 1 : 59);
+
+        /* Now wait for it to change, be moved or deleted */
+        if (wd >= 0)
+        {
+            char buf[4096];
+            VERB3 log("Waiting for '%s' to change", filename);
+            /* We block here: */
+            int len = read(inotify_fd, buf, sizeof(buf));
+            if (len < 0 && errno != EINTR) /* I saw EINTR here on strace attach */
+                perror_msg("Error reading inotify fd");
+            /* we don't actually check what happened to file -
+             * the code will handle all possibilities.
+             */
+            VERB3 log("Change in '%s' detected", filename);
+            /* Let them finish writing to the log file. otherwise
+             * we may end up trying to analyze partial oops.
+             */
+            sleep(1);
+        }
+
+    } /* while (1) */
+
+    return 0;
+}
diff -x '*.po' -d -urpN abrt.1/src/plugins/Makefile.am abrt.2/src/plugins/Makefile.am
--- abrt.1/src/plugins/Makefile.am	2012-02-28 14:29:11.000000000 +0100
+++ abrt.2/src/plugins/Makefile.am	2012-03-14 03:14:31.418176392 +0100
@@ -7,6 +7,7 @@ bin_SCRIPTS = \
     abrt-action-list-dsos
 
 bin_PROGRAMS = \
+    abrt-watch-log \
     abrt-dump-oops \
     abrt-action-analyze-c \
     abrt-action-analyze-python \
@@ -69,6 +70,20 @@ EXTRA_DIST = \
     abrt-action-analyze-vmcore \
     https-utils.h
 
+abrt_watch_log_SOURCES = \
+    abrt-watch-log.c
+abrt_watch_log_CPPFLAGS = \
+    -I$(srcdir)/../include \
+    -I$(srcdir)/../lib \
+    $(GLIB_CFLAGS) \
+    $(LIBREPORT_CFLAGS) \
+    -D_GNU_SOURCE \
+    -Wall -Wwrite-strings -Werror
+abrt_watch_log_LDADD = \
+    $(GLIB_LIBS) \
+    $(LIBREPORT_LIBS) \
+    ../lib/libabrt.la
+
 abrt_dump_oops_SOURCES = \
     abrt-dump-oops.c
 abrt_dump_oops_CPPFLAGS = \
diff -x '*.po' -d -urpN abrt.1/tests/runtests/dumpoops/runtest.sh abrt.2/tests/runtests/dumpoops/runtest.sh
--- abrt.1/tests/runtests/dumpoops/runtest.sh	2011-11-22 15:19:35.000000000 +0100
+++ abrt.2/tests/runtests/dumpoops/runtest.sh	2012-03-14 13:19:36.179418713 +0100
@@ -39,13 +39,13 @@ rlJournalStart
 
     rlPhaseStartTest OOPS
         for oops in oops*.test; do
-            rlRun "abrt-dump-oops $oops 2>&1 | grep 'abrt-dump-oops: Found oopses: [1-9]'" 0 "[$oops] Found OOPS"
+            rlRun "abrt-dump-oops <$oops 2>&1 | grep 'abrt-dump-oops: Found oopses: [1-9]'" 0 "[$oops] Found OOPS"
         done
     rlPhaseEnd
 
     rlPhaseStartTest not-OOPS
         for noops in not_oops*.test; do
-            rlRun "abrt-dump-oops $noops 2>&1 | grep 'abrt-dump-oops: Found oopses: 0'" 0 "[$noops] Not found OOPS"
+            rlRun "abrt-dump-oops <$noops 2>&1 | grep 'abrt-dump-oops: Found oopses: 0'" 0 "[$noops] Not found OOPS"
         done
     rlPhaseEnd
 
