Date: Thu, 20 Jun 2002 08:03:44 -0700 (PDT) From: Ryoji KANAI <kanai@big.or.jp> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/39576: [PATCH] tail -f for multiple files Message-ID: <200206201503.g5KF3i4h041725@www.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 39576
>Category: bin
>Synopsis: [PATCH] tail -f for multiple files
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Thu Jun 20 08:10:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Ryoji KANAI
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:
FreeBSD unicorn 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Tue May 21 01:04:57 JST 2002 kanai@unicorn:/var/usr.src/sys/i386/compile/UNICORN i386
extern.h 1.8
tail.c 1.14
forward.c 1.31
>Description:
The following patch adds the tail -f for multiple files
ex:
% tail -f /var/log/maillog /var/log/popper
>How-To-Repeat:
>Fix:
diff -cur /usr/src/usr.bin/tail/extern.h ./newtail/extern.h
--- /usr/src/usr.bin/tail/extern.h Fri Mar 22 10:42:32 2002
+++ ./newtail/extern.h Thu Jun 20 00:29:30 2002
@@ -50,10 +50,18 @@
int fd;
};
+struct file_spec {
+ const char *name;
+ int fd;
+ FILE *fp;
+ struct stat sb;
+};
enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
void forward(FILE *, enum STYLE, off_t, struct stat *);
void reverse(FILE *, enum STYLE, off_t, struct stat *);
+
+void forever(struct file_spec*, const int);
int bytes(FILE *, off_t);
int lines(FILE *, off_t);
diff -cur /usr/src/usr.bin/tail/forward.c ./newtail/forward.c
--- /usr/src/usr.bin/tail/forward.c Fri May 17 22:46:21 2002
+++ ./newtail/forward.c Thu Jun 20 00:34:40 2002
@@ -95,11 +95,7 @@
off_t off;
struct stat *sbp;
{
- int ch, n, kq = -1;
- int action = USE_SLEEP;
- struct kevent ev[2];
- struct stat sb2;
- struct timespec ts;
+ int ch;
switch(style) {
case FBYTES:
@@ -176,25 +172,31 @@
break;
}
- if (fflag) {
- kq = kqueue();
- if (kq < 0)
- err(1, "kqueue");
- action = ADD_EVENTS;
- }
+}
+void forever(fs, n_files)
+ struct file_spec *fs;
+ const int n_files;
+{
+ int ch, n, kq = -1;
+ int action = USE_SLEEP;
+ int i, last, ev_vnode, ev_read;
+
+ struct stat sb2;
+ struct kevent *ev;
+ struct timespec ts;
+
+ kq = kqueue();
+ if (kq < 0)
+ err(1, "kqueue");
+ action = ADD_EVENTS;
+
+ ev = malloc(sizeof(struct kevent) * n_files * 2);
+
+ last = n_files - 1;
for (;;) {
- while ((ch = getc(fp)) != EOF)
- if (putchar(ch) == EOF)
- oerr();
- if (ferror(fp)) {
- ierr();
- return;
- }
- (void)fflush(stdout);
- if (! fflag)
- break;
- clearerr(fp);
+ ev_vnode = -1;
+ ev_read = -1;
switch (action) {
case ADD_EVENTS:
@@ -202,15 +204,17 @@
ts.tv_sec = 0;
ts.tv_nsec = 0;
- if (Fflag && fileno(fp) != STDIN_FILENO) {
- EV_SET(&ev[n], fileno(fp), EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_CLEAR,
- NOTE_DELETE | NOTE_RENAME, 0, 0);
+ for(i = 0; i< n_files; i++){
+ if (Fflag && fs[i].fd != STDIN_FILENO) {
+ EV_SET(&ev[n], fs[i].fd, EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE | NOTE_RENAME, 0, 0);
+ n++;
+ }
+ EV_SET(&ev[n], fs[i].fd, EVFILT_READ,
+ EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
n++;
}
- EV_SET(&ev[n], fileno(fp), EVFILT_READ,
- EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
- n++;
if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
action = USE_SLEEP;
@@ -231,41 +235,71 @@
err(1, "kevent");
if (n == 0) {
/* timeout */
+ ev_vnode = -1;
break;
- } else if (ev->filter == EVFILT_READ && ev->data < 0) {
- /* file shrank, reposition to end */
- if (fseeko(fp, (off_t)0, SEEK_END) == -1) {
- ierr();
- return;
+ } else if (ev->filter == EVFILT_READ){
+ ev_read = ev[0].ident;
+ if(ev->data < 0) {
+ /* file shrank, reposition to end */
+ if (lseek(ev[0].ident, (off_t)0,
+ SEEK_END) == -1) {
+ ierr();
+ return;
+ }
}
+ } else {
+ ev_vnode = ev[0].ident;
}
break;
case USE_SLEEP:
(void) usleep(250000);
- clearerr(fp);
break;
}
- if (Fflag && fileno(fp) != STDIN_FILENO) {
- while (stat(fname, &sb2) != 0)
- /* file was rotated, wait until it reappears */
- (void)sleep(1);
- if (sb2.st_ino != sbp->st_ino ||
- sb2.st_dev != sbp->st_dev ||
- sb2.st_rdev != sbp->st_rdev ||
- sb2.st_nlink == 0) {
- fp = freopen(fname, "r", fp);
- if (fp == NULL) {
+ for(i = 0; i < n_files; i++){
+ if(action == USE_SLEEP || ev_read == fs[i].fd){
+ while ((ch = getc(fs[i].fp)) != EOF){
+ if(last != i){
+ printf("\n==> %s <==\n",
+ fs[i].name);
+ last = i;
+ }
+ if (putchar(ch) == EOF)
+ oerr();
+ }
+ if (ferror(fs[i].fp)) {
ierr();
- } else {
- *sbp = sb2;
- action = ADD_EVENTS;
+ return;
+ }
+ (void)fflush(stdout);
+ clearerr(fs[i].fp);
+ }
+
+ if(Fflag && fs[i].fd != STDIN_FILENO &&
+ (ev_vnode == -1 || ev_vnode == fs[i].fd)) {
+ /* file was rotated, wait until it reappears */
+ while (stat(fs[i].name, &sb2) != 0)
+ (void)sleep(1);
+ if (sb2.st_ino != fs[i].sb.st_ino ||
+ sb2.st_dev != fs[i].sb.st_dev ||
+ sb2.st_rdev != fs[i].sb.st_rdev ||
+ sb2.st_nlink == 0) {
+ fs[i].fp = freopen(fs[i].name, "r",
+ fs[i].fp);
+ fs[i].fd = fileno(fs[i].fp);
+ if (fs[i].fp == NULL) {
+ ierr();
+ } else {
+ fs[i].sb = sb2;
+ action = ADD_EVENTS;
+ }
}
}
}
}
}
+
/*
* rlines -- display the last offset lines of the file.
diff -cur /usr/src/usr.bin/tail/tail.c ./newtail/tail.c
--- /usr/src/usr.bin/tail/tail.c Fri Mar 22 10:42:32 2002
+++ ./newtail/tail.c Thu Jun 20 23:35:01 2002
@@ -72,10 +72,11 @@
char *argv[];
{
struct stat sb;
+ struct file_spec *fs;
FILE *fp;
off_t off;
enum STYLE style;
- int ch, first;
+ int ch, first, n_files;
char *p;
/*
@@ -140,9 +141,6 @@
argc -= optind;
argv += optind;
- if (fflag && argc > 1)
- errx(1, "-f option only appropriate for a single file");
-
/*
* If displaying in reverse, don't permit follow option, and convert
* style values.
@@ -170,7 +168,10 @@
}
}
- if (*argv)
+ fs = malloc(sizeof(struct file_spec) * argc);
+
+ if (*argv) {
+ n_files = 0;
for (first = 1; (fname = *argv++);) {
if ((fp = fopen(fname, "r")) == NULL ||
fstat(fileno(fp), &sb)) {
@@ -188,9 +189,20 @@
reverse(fp, style, off, &sb);
else
forward(fp, style, off, &sb);
- (void)fclose(fp);
+
+ if (fflag) {
+ fs[n_files].name = fname;
+ fs[n_files].fp = fp;
+ fs[n_files].fd = fileno(fp);
+ fs[n_files].sb = sb;
+ n_files++;
+ } else {
+ (void)fclose(fp);
+ }
}
- else {
+ if (fflag)
+ forever(fs, n_files);
+ } else {
fname = "stdin";
if (fstat(fileno(stdin), &sb)) {
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200206201503.g5KF3i4h041725>
