summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2009-06-05 09:08:53 +0000
committerbrian <brian@FreeBSD.org>2009-06-05 09:08:53 +0000
commit330bc8582df629e9fa4dccb68bbab181520d98a9 (patch)
treee543b101f94f862f5071b48f0a4c466e2afa6f25
parentc284a3411ae19dfa5dbf2a027bbbd7aa24ff1191 (diff)
downloadFreeBSD-src-330bc8582df629e9fa4dccb68bbab181520d98a9.zip
FreeBSD-src-330bc8582df629e9fa4dccb68bbab181520d98a9.tar.gz
Change the behaviour of -F slightly; it now persists (forever) in
trying to open files rather than giving up when it encounters an error. ENOENT errors are not reported. As a result, files that are moved away then recreated are not at risk of being 'lost' to tail. Files that are recreated and temporarily have unreadable permissions will be shown when they are fixed. This behaviour is consistent with the GNU version of tail but without the verbiage that goes with the GNU version. This change also fixes error messages accompanying -f and -F. They no longer report problems with (null)! MFC after: 3 weeks
-rw-r--r--usr.bin/tail/extern.h11
-rw-r--r--usr.bin/tail/forward.c150
-rw-r--r--usr.bin/tail/misc.c2
-rw-r--r--usr.bin/tail/read.c8
-rw-r--r--usr.bin/tail/reverse.c28
-rw-r--r--usr.bin/tail/tail.111
-rw-r--r--usr.bin/tail/tail.c41
7 files changed, 144 insertions, 107 deletions
diff --git a/usr.bin/tail/extern.h b/usr.bin/tail/extern.h
index d956680..f91495d 100644
--- a/usr.bin/tail/extern.h
+++ b/usr.bin/tail/extern.h
@@ -61,16 +61,15 @@ typedef struct file_info file_info_t;
enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
void follow(file_info_t *, enum STYLE, off_t);
-void forward(FILE *, enum STYLE, off_t, struct stat *);
-void reverse(FILE *, enum STYLE, off_t, struct stat *);
+void forward(FILE *, const char *, enum STYLE, off_t, struct stat *);
+void reverse(FILE *, const char *, enum STYLE, off_t, struct stat *);
-int bytes(FILE *, off_t);
-int lines(FILE *, off_t);
+int bytes(FILE *, const char *, off_t);
+int lines(FILE *, const char *, off_t);
-void ierr(void);
+void ierr(const char *);
void oerr(void);
int mapprint(struct mapinfo *, off_t, off_t);
int maparound(struct mapinfo *, off_t);
extern int Fflag, fflag, qflag, rflag, rval, no_files;
-extern const char *fname;
diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c
index c79c438..6dab72e 100644
--- a/usr.bin/tail/forward.c
+++ b/usr.bin/tail/forward.c
@@ -61,8 +61,8 @@ static const char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93";
#include "extern.h"
-static void rlines(FILE *, off_t, struct stat *);
-static void show(file_info_t *);
+static void rlines(FILE *, const char *fn, off_t, struct stat *);
+static int show(file_info_t *);
static void set_events(file_info_t *files);
/* defines for inner loop actions */
@@ -99,7 +99,7 @@ static const file_info_t *last;
* NOREG cyclically read lines into a wrap-around array of buffers
*/
void
-forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+forward(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
{
int ch;
@@ -111,13 +111,13 @@ forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
if (sbp->st_size < off)
off = sbp->st_size;
if (fseeko(fp, off, SEEK_SET) == -1) {
- ierr();
+ ierr(fn);
return;
}
} else while (off--)
if ((ch = getc(fp)) == EOF) {
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
break;
@@ -129,7 +129,7 @@ forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
for (;;) {
if ((ch = getc(fp)) == EOF) {
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
break;
@@ -142,36 +142,36 @@ forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
if (S_ISREG(sbp->st_mode)) {
if (sbp->st_size >= off &&
fseeko(fp, -off, SEEK_END) == -1) {
- ierr();
+ ierr(fn);
return;
}
} else if (off == 0) {
while (getc(fp) != EOF);
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
} else
- if (bytes(fp, off))
+ if (bytes(fp, fn, off))
return;
break;
case RLINES:
if (S_ISREG(sbp->st_mode))
if (!off) {
if (fseeko(fp, (off_t)0, SEEK_END) == -1) {
- ierr();
+ ierr(fn);
return;
}
} else
- rlines(fp, off, sbp);
+ rlines(fp, fn, off, sbp);
else if (off == 0) {
while (getc(fp) != EOF);
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
} else
- if (lines(fp, off))
+ if (lines(fp, fn, off))
return;
break;
default:
@@ -182,7 +182,7 @@ forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
if (putchar(ch) == EOF)
oerr();
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
(void)fflush(stdout);
@@ -192,10 +192,7 @@ forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
* rlines -- display the last offset lines of the file.
*/
static void
-rlines(fp, off, sbp)
- FILE *fp;
- off_t off;
- struct stat *sbp;
+rlines(FILE *fp, const char *fn, off_t off, struct stat *sbp)
{
struct mapinfo map;
off_t curoff, size;
@@ -214,7 +211,7 @@ rlines(fp, off, sbp)
curoff = size - 2;
while (curoff >= 0) {
if (curoff < map.mapoff && maparound(&map, curoff) != 0) {
- ierr();
+ ierr(fn);
return;
}
for (i = curoff - map.mapoff; i >= 0; i--)
@@ -227,41 +224,44 @@ rlines(fp, off, sbp)
}
curoff++;
if (mapprint(&map, curoff, size - curoff) != 0) {
- ierr();
+ ierr(fn);
exit(1);
}
/* Set the file pointer to reflect the length displayed. */
if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) {
- ierr();
+ ierr(fn);
return;
}
if (map.start != NULL && munmap(map.start, map.maplen)) {
- ierr();
+ ierr(fn);
return;
}
}
-static void
+static int
show(file_info_t *file)
{
- int ch;
+ int ch;
- while ((ch = getc(file->fp)) != EOF) {
- if (last != file && no_files > 1) {
- if (!qflag)
- (void)printf("\n==> %s <==\n", file->file_name);
- last = file;
+ while ((ch = getc(file->fp)) != EOF) {
+ if (last != file && no_files > 1) {
+ if (!qflag)
+ (void)printf("\n==> %s <==\n", file->file_name);
+ last = file;
+ }
+ if (putchar(ch) == EOF)
+ oerr();
+ }
+ (void)fflush(stdout);
+ if (ferror(file->fp)) {
+ fclose(file->fp);
+ file->fp = NULL;
+ ierr(file->file_name);
+ return 0;
}
- if (putchar(ch) == EOF)
- oerr();
- }
- (void)fflush(stdout);
- if (ferror(file->fp)) {
- file->fp = NULL;
- ierr();
- } else
- clearerr(file->fp);
+ clearerr(file->fp);
+ return 1;
}
static void
@@ -309,7 +309,7 @@ set_events(file_info_t *files)
void
follow(file_info_t *files, enum STYLE style, off_t off)
{
- int active, i, n = -1;
+ int active, ev_change, i, n = -1;
struct stat sb2;
file_info_t *file;
struct timespec ts;
@@ -325,12 +325,12 @@ follow(file_info_t *files, enum STYLE style, off_t off)
n++;
if (no_files > 1 && !qflag)
(void)printf("\n==> %s <==\n", file->file_name);
- forward(file->fp, style, off, &file->st);
+ forward(file->fp, file->file_name, style, off, &file->st);
if (Fflag && fileno(file->fp) != STDIN_FILENO)
- n++;
+ n++;
}
}
- if (! active)
+ if (!Fflag && !active)
return;
last = --file;
@@ -344,28 +344,56 @@ follow(file_info_t *files, enum STYLE style, off_t off)
set_events(files);
for (;;) {
- for (i = 0, file = files; i < no_files; i++, file++) {
- if (! file->fp)
- continue;
- if (Fflag && file->fp && fileno(file->fp) != STDIN_FILENO) {
- if (stat(file->file_name, &sb2) == 0 &&
- (sb2.st_ino != file->st.st_ino ||
- sb2.st_dev != file->st.st_dev ||
- sb2.st_nlink == 0)) {
- show(file);
- file->fp = freopen(file->file_name, "r", file->fp);
- if (file->fp == NULL) {
- ierr();
- continue;
- } else {
- memcpy(&file->st, &sb2, sizeof(struct stat));
- set_events(files);
+ ev_change = 0;
+ if (Fflag) {
+ for (i = 0, file = files; i < no_files; i++, file++) {
+ if (!file->fp) {
+ file->fp = fopen(file->file_name, "r");
+ if (file->fp != NULL &&
+ fstat(fileno(file->fp), &file->st)
+ == -1) {
+ fclose(file->fp);
+ file->fp = NULL;
}
+ if (file->fp != NULL)
+ ev_change++;
+ continue;
+ }
+ if (fileno(file->fp) == STDIN_FILENO)
+ continue;
+ if (stat(file->file_name, &sb2) == -1) {
+ if (errno != ENOENT)
+ ierr(file->file_name);
+ show(file);
+ fclose(file->fp);
+ file->fp = NULL;
+ ev_change++;
+ continue;
+ }
+
+ if (sb2.st_ino != file->st.st_ino ||
+ sb2.st_dev != file->st.st_dev ||
+ sb2.st_nlink == 0) {
+ show(file);
+ file->fp = freopen(file->file_name, "r",
+ file->fp);
+ if (file->fp != NULL)
+ memcpy(&file->st, &sb2,
+ sizeof(struct stat));
+ else if (errno != ENOENT)
+ ierr(file->file_name);
+ ev_change++;
}
}
- show(file);
}
+ for (i = 0, file = files; i < no_files; i++, file++)
+ if (file->fp && !show(file))
+ ev_change++;
+
+ if (ev_change)
+ set_events(files);
+
switch (action) {
case USE_KQUEUE:
ts.tv_sec = 1;
@@ -381,9 +409,9 @@ follow(file_info_t *files, enum STYLE style, off_t off)
/* timeout */
break;
} else if (ev->filter == EVFILT_READ && ev->data < 0) {
- /* file shrank, reposition to end */
+ /* file shrank, reposition to end */
if (lseek(ev->ident, (off_t)0, SEEK_END) == -1) {
- ierr();
+ ierr(file->file_name);
continue;
}
}
diff --git a/usr.bin/tail/misc.c b/usr.bin/tail/misc.c
index 584e3d1..7e57504 100644
--- a/usr.bin/tail/misc.c
+++ b/usr.bin/tail/misc.c
@@ -56,7 +56,7 @@ static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
#include "extern.h"
void
-ierr()
+ierr(const char *fname)
{
warn("%s", fname);
rval = 1;
diff --git a/usr.bin/tail/read.c b/usr.bin/tail/read.c
index d290ed4..14086e7 100644
--- a/usr.bin/tail/read.c
+++ b/usr.bin/tail/read.c
@@ -66,7 +66,7 @@ static const char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93";
* the end.
*/
int
-bytes(FILE *fp, off_t off)
+bytes(FILE *fp, const char *fn, off_t off)
{
int ch, len, tlen;
char *ep, *p, *t;
@@ -84,7 +84,7 @@ bytes(FILE *fp, off_t off)
}
}
if (ferror(fp)) {
- ierr();
+ ierr(fn);
free(sp);
return 1;
}
@@ -136,7 +136,7 @@ bytes(FILE *fp, off_t off)
* the end.
*/
int
-lines(FILE *fp, off_t off)
+lines(FILE *fp, const char *fn, off_t off)
{
struct {
int blen;
@@ -178,7 +178,7 @@ lines(FILE *fp, off_t off)
}
}
if (ferror(fp)) {
- ierr();
+ ierr(fn);
rc = 1;
goto done;
}
diff --git a/usr.bin/tail/reverse.c b/usr.bin/tail/reverse.c
index 462b392..d86c46b 100644
--- a/usr.bin/tail/reverse.c
+++ b/usr.bin/tail/reverse.c
@@ -58,8 +58,8 @@ __FBSDID("$FreeBSD$");
#include "extern.h"
-static void r_buf(FILE *);
-static void r_reg(FILE *, enum STYLE, off_t, struct stat *);
+static void r_buf(FILE *, const char *);
+static void r_reg(FILE *, const char *, enum STYLE, off_t, struct stat *);
/*
* reverse -- display input in reverse order by line.
@@ -80,25 +80,25 @@ static void r_reg(FILE *, enum STYLE, off_t, struct stat *);
* NOREG cyclically read input into a linked list of buffers
*/
void
-reverse(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+reverse(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
{
if (style != REVERSE && off == 0)
return;
if (S_ISREG(sbp->st_mode))
- r_reg(fp, style, off, sbp);
+ r_reg(fp, fn, style, off, sbp);
else
switch(style) {
case FBYTES:
case RBYTES:
- bytes(fp, off);
+ bytes(fp, fn, off);
break;
case FLINES:
case RLINES:
- lines(fp, off);
+ lines(fp, fn, off);
break;
case REVERSE:
- r_buf(fp);
+ r_buf(fp, fn);
break;
default:
break;
@@ -109,7 +109,7 @@ reverse(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
* r_reg -- display a regular file in reverse order by line.
*/
static void
-r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+r_reg(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
{
struct mapinfo map;
off_t curoff, size, lineend;
@@ -132,7 +132,7 @@ r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
if (curoff < map.mapoff ||
curoff >= map.mapoff + (off_t)map.maplen) {
if (maparound(&map, curoff) != 0) {
- ierr();
+ ierr(fn);
return;
}
}
@@ -149,7 +149,7 @@ r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
/* Print the line and update offsets. */
if (mapprint(&map, curoff + 1, lineend - curoff - 1) != 0) {
- ierr();
+ ierr(fn);
return;
}
lineend = curoff + 1;
@@ -165,11 +165,11 @@ r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
}
}
if (curoff < 0 && mapprint(&map, 0, lineend) != 0) {
- ierr();
+ ierr(fn);
return;
}
if (map.start != NULL && munmap(map.start, map.maplen))
- ierr();
+ ierr(fn);
}
typedef struct bf {
@@ -190,7 +190,7 @@ typedef struct bf {
* user warned).
*/
static void
-r_buf(FILE *fp)
+r_buf(FILE *fp, const char *fn)
{
BF *mark, *tl, *tr;
int ch, len, llen;
@@ -227,7 +227,7 @@ r_buf(FILE *fp)
*p++ = ch;
if (ferror(fp)) {
- ierr();
+ ierr(fn);
return;
}
diff --git a/usr.bin/tail/tail.1 b/usr.bin/tail/tail.1
index 251511a..7f91e71 100644
--- a/usr.bin/tail/tail.1
+++ b/usr.bin/tail/tail.1
@@ -35,7 +35,7 @@
.\" @(#)tail.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd June 29, 2006
+.Dd June 05, 2009
.Dt TAIL 1
.Os
.Sh NAME
@@ -106,9 +106,16 @@ will also check to see if the file being followed has been renamed or rotated.
The file is closed and reopened when
.Nm
detects that the filename being read from has a new inode number.
+.Pp
+If the file being followed does not (yet) exist or if it is removed, tail
+will keep looking and will display the file from the beginning if and when
+it is created.
+.Pp
The
.Fl F
-option is ignored if reading from standard input rather than a file.
+option is the same as the
+.Fl f
+option if reading from standard input rather than a file.
.It Fl n Ar number
The location is
.Ar number
diff --git a/usr.bin/tail/tail.c b/usr.bin/tail/tail.c
index d2f9df7..0a807ee 100644
--- a/usr.bin/tail/tail.c
+++ b/usr.bin/tail/tail.c
@@ -61,7 +61,6 @@ static const char sccsid[] = "@(#)tail.c 8.1 (Berkeley) 6/6/93";
#include "extern.h"
int Fflag, fflag, qflag, rflag, rval, no_files;
-const char *fname;
file_info_t *files;
@@ -72,6 +71,7 @@ int
main(int argc, char *argv[])
{
struct stat sb;
+ const char *fn;
FILE *fp;
off_t off;
enum STYLE style;
@@ -175,20 +175,23 @@ main(int argc, char *argv[])
}
if (*argv && fflag) {
- files = (struct file_info *) malloc(no_files * sizeof(struct file_info));
- if (! files)
+ files = (struct file_info *) malloc(no_files *
+ sizeof(struct file_info));
+ if (!files)
err(1, "Couldn't malloc space for file descriptors.");
- for (file = files; (fname = *argv++); file++) {
- file->file_name = malloc(strlen(fname)+1);
+ for (file = files; (fn = *argv++); file++) {
+ file->file_name = strdup(fn);
if (! file->file_name)
errx(1, "Couldn't malloc space for file name.");
- strncpy(file->file_name, fname, strlen(fname)+1);
if ((file->fp = fopen(file->file_name, "r")) == NULL ||
fstat(fileno(file->fp), &file->st)) {
- file->fp = NULL;
- ierr();
- continue;
+ if (file->fp != NULL) {
+ fclose(file->fp);
+ file->fp = NULL;
+ }
+ if (!Fflag || errno != ENOENT)
+ ierr(file->file_name);
}
}
follow(files, style, off);
@@ -197,29 +200,29 @@ main(int argc, char *argv[])
}
free(files);
} else if (*argv) {
- for (first = 1; (fname = *argv++);) {
- if ((fp = fopen(fname, "r")) == NULL ||
+ for (first = 1; (fn = *argv++);) {
+ if ((fp = fopen(fn, "r")) == NULL ||
fstat(fileno(fp), &sb)) {
- ierr();
+ ierr(fn);
continue;
}
if (argc > 1 && !qflag) {
(void)printf("%s==> %s <==\n",
- first ? "" : "\n", fname);
+ first ? "" : "\n", fn);
first = 0;
(void)fflush(stdout);
}
if (rflag)
- reverse(fp, style, off, &sb);
+ reverse(fp, fn, style, off, &sb);
else
- forward(fp, style, off, &sb);
+ forward(fp, fn, style, off, &sb);
}
} else {
- fname = "stdin";
+ fn = "stdin";
if (fstat(fileno(stdin), &sb)) {
- ierr();
+ ierr(fn);
exit(1);
}
@@ -234,9 +237,9 @@ main(int argc, char *argv[])
}
if (rflag)
- reverse(stdin, style, off, &sb);
+ reverse(stdin, fn, style, off, &sb);
else
- forward(stdin, style, off, &sb);
+ forward(stdin, fn, style, off, &sb);
}
exit(rval);
}
OpenPOWER on IntegriCloud