--- tail.c.orig 2004-07-19 13:03:26.281206328 +0000 +++ tail.c 2004-07-19 17:00:59.314415928 +0000 @@ -106,6 +106,13 @@ dev_t dev; ino_t ino; + /* Whether this file is a FIFO */ + int fifo; + + /* Whether this file is a FIFO and we received eof last time we read from it + * */ + int read_eof; + /* The specified name initially referred to a directory or some other type for which tail isn't meaningful. Unlike for a permission problem (tailable, below) once this is set, the name is not checked ever again. */ @@ -971,6 +978,7 @@ { int last; int writer_is_dead = 0; + int fifo_read = 0; last = nfiles - 1; @@ -978,11 +986,18 @@ { int i; int any_changed; + int skip_fifo; any_changed = 0; + + skip_fifo = fifo_read; + fifo_read = 0; + for (i = 0; i < nfiles; i++) { struct stat stats; + int bytes_read; + if (f[i].ignore) continue; @@ -993,37 +1008,58 @@ continue; } - if (fstat (f[i].fd, &stats) < 0) - { - f[i].fd = -1; - f[i].errnum = errno; - error (0, errno, "%s", pretty_name (&f[i])); - continue; - } - - if (stats.st_size == f[i].size) - { - f[i].n_consecutive_size_changes = 0; - if ((max_n_unchanged_stats_between_opens - <= f[i].n_unchanged_stats++) - && follow_mode == Follow_name) - { - recheck (&f[i]); - f[i].n_unchanged_stats = 0; - } - continue; - } - - /* Ensure that a file that's unlinked or moved aside, yet always - growing will be recognized as having been renamed. */ - if ((max_n_consecutive_size_changes_between_opens - <= f[i].n_consecutive_size_changes++) - && follow_mode == Follow_name) - { - f[i].n_consecutive_size_changes = 0; - recheck (&f[i]); - continue; - } + if (f[i].fifo) + { + if (f[i].read_eof == 1 || skip_fifo) + { + f[i].read_eof = 0; + continue; + } + } + else + { + if (fstat (f[i].fd, &stats) < 0) + { + f[i].fd = -1; + f[i].errnum = errno; + error (0, errno, "%s", pretty_name (&f[i])); + continue; + } + + if (stats.st_size == f[i].size) + { + f[i].n_consecutive_size_changes = 0; + if ((max_n_unchanged_stats_between_opens + <= f[i].n_unchanged_stats++) + && follow_mode == Follow_name) + { + recheck (&f[i]); + f[i].n_unchanged_stats = 0; + } + continue; + } + + /* Ensure that a file that's unlinked or moved aside, yet always + growing will be recognized as having been renamed. */ + if ((max_n_consecutive_size_changes_between_opens + <= f[i].n_consecutive_size_changes++) + && follow_mode == Follow_name) + { + f[i].n_consecutive_size_changes = 0; + recheck (&f[i]); + continue; + } + + if (stats.st_size < f[i].size) + { + error (0, 0, _("%s: file truncated"), pretty_name (&f[i])); + last = i; + xlseek (f[i].fd, (off_t) stats.st_size, SEEK_SET, + pretty_name (&f[i])); + f[i].size = stats.st_size; + continue; + } + } /* This file has changed size. Print out what we can, and then keep looping. */ @@ -1033,15 +1069,6 @@ /* reset counter */ f[i].n_unchanged_stats = 0; - if (stats.st_size < f[i].size) - { - error (0, 0, _("%s: file truncated"), pretty_name (&f[i])); - last = i; - xlseek (f[i].fd, (off_t) stats.st_size, SEEK_SET, - pretty_name (&f[i])); - f[i].size = stats.st_size; - continue; - } if (i != last) { @@ -1049,8 +1076,23 @@ write_header (pretty_name (&f[i])); last = i; } - f[i].size += dump_remainder (pretty_name (&f[i]), f[i].fd, + bytes_read = dump_remainder (pretty_name (&f[i]), f[i].fd, COPY_TO_EOF); + if (f[i].fifo == 1) + { + if (bytes_read == 0) + { + f[i].read_eof = 1; + } + else + { + fifo_read = 1; + } + } + else + { + f[i].size += bytes_read; + } } if (n_live_files (f, nfiles) == 0 && ! reopen_inaccessible_files) @@ -1250,7 +1292,7 @@ } else { - fd = open (f->name, O_RDONLY); + fd = open (f->name, O_RDONLY | O_NONBLOCK); } f->tailable = !(reopen_inaccessible_files && fd == -1); @@ -1321,6 +1363,14 @@ f->n_unchanged_stats = 0; f->n_consecutive_size_changes = 0; f->ignore = 0; + if (S_ISFIFO (stats.st_mode)) + { + f->fifo = 1; + } + else + { + f->fifo = 0; + } } } else