make tail work like head for multiple files
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Wed, 4 Mar 1992 08:13:36 +0000 (00:13 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Wed, 4 Mar 1992 08:13:36 +0000 (00:13 -0800)
SCCS-vsn: usr.bin/tail/extern.h 5.2
SCCS-vsn: usr.bin/tail/forward.c 5.5
SCCS-vsn: usr.bin/tail/misc.c 5.2
SCCS-vsn: usr.bin/tail/read.c 5.2
SCCS-vsn: usr.bin/tail/reverse.c 5.4
SCCS-vsn: usr.bin/tail/tail.1 6.9
SCCS-vsn: usr.bin/tail/tail.c 5.8

usr/src/usr.bin/tail/extern.h
usr/src/usr.bin/tail/forward.c
usr/src/usr.bin/tail/misc.c
usr/src/usr.bin/tail/read.c
usr/src/usr.bin/tail/reverse.c
usr/src/usr.bin/tail/tail.1
usr/src/usr.bin/tail/tail.c

index 0e7b66a..98db668 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)extern.h    5.1 (Berkeley) %G%
+ *     @(#)extern.h    5.2 (Berkeley) %G%
  */
 
 #define        WR(p, size) \
  */
 
 #define        WR(p, size) \
@@ -19,7 +19,7 @@ void  reverse __P((FILE *, enum STYLE, long, struct stat *));
 void   bytes __P((FILE *, off_t));
 void   lines __P((FILE *, off_t));
 
 void   bytes __P((FILE *, off_t));
 void   lines __P((FILE *, off_t));
 
-void   err __P((const char *fmt, ...));
+void   err __P((int fatal, const char *fmt, ...));
 void   ierr __P((void));
 void   oerr __P((void));
 
 void   ierr __P((void));
 void   oerr __P((void));
 
index c6e4510..7a61111 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)forward.c  5.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)forward.c  5.5 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -66,22 +66,28 @@ forward(fp, style, off, sbp)
                if (S_ISREG(sbp->st_mode)) {
                        if (sbp->st_size < off)
                                off = sbp->st_size;
                if (S_ISREG(sbp->st_mode)) {
                        if (sbp->st_size < off)
                                off = sbp->st_size;
-                       if (fseek(fp, off, SEEK_SET) == -1)
+                       if (fseek(fp, off, SEEK_SET) == -1) {
                                ierr();
                                ierr();
+                               return;
+                       }
                } else while (off--)
                        if ((ch = getc(fp)) == EOF) {
                } else while (off--)
                        if ((ch = getc(fp)) == EOF) {
-                               if (ferror(fp))
+                               if (ferror(fp)) {
                                        ierr();
                                        ierr();
-                                       break;
+                                       return;
                                }
                                }
+                               break;
+                       }
                break;
        case FLINES:
                if (off == 0)
                        break;
                for (;;) {
                        if ((ch = getc(fp)) == EOF) {
                break;
        case FLINES:
                if (off == 0)
                        break;
                for (;;) {
                        if ((ch = getc(fp)) == EOF) {
-                               if (ferror(fp))
+                               if (ferror(fp)) {
                                        ierr();
                                        ierr();
+                                       return;
+                               }
                                break;
                        }
                        if (ch == '\n' && !--off)
                                break;
                        }
                        if (ch == '\n' && !--off)
@@ -91,26 +97,34 @@ forward(fp, style, off, sbp)
        case RBYTES:
                if (S_ISREG(sbp->st_mode)) {
                        if (sbp->st_size >= off &&
        case RBYTES:
                if (S_ISREG(sbp->st_mode)) {
                        if (sbp->st_size >= off &&
-                           fseek(fp, -off, SEEK_END) == -1)
+                           fseek(fp, -off, SEEK_END) == -1) {
                                ierr();
                                ierr();
+                               return;
+                       }
                } else if (off == 0) {
                        while (getc(fp) != EOF);
                } else if (off == 0) {
                        while (getc(fp) != EOF);
-                       if (ferror(fp))
+                       if (ferror(fp)) {
                                ierr();
                                ierr();
+                               return;
+                       }
                } else
                        bytes(fp, off);
                break;
        case RLINES:
                if (S_ISREG(sbp->st_mode))
                        if (!off) {
                } else
                        bytes(fp, off);
                break;
        case RLINES:
                if (S_ISREG(sbp->st_mode))
                        if (!off) {
-                               if (fseek(fp, 0L, SEEK_END) == -1)
+                               if (fseek(fp, 0L, SEEK_END) == -1) {
                                        ierr();
                                        ierr();
+                                       return;
+                               }
                        } else
                                rlines(fp, off, sbp);
                else if (off == 0) {
                        while (getc(fp) != EOF);
                        } else
                                rlines(fp, off, sbp);
                else if (off == 0) {
                        while (getc(fp) != EOF);
-                       if (ferror(fp))
+                       if (ferror(fp)) {
                                ierr();
                                ierr();
+                               return;
+                       }
                } else
                        lines(fp, off);
                break;
                } else
                        lines(fp, off);
                break;
@@ -130,14 +144,16 @@ forward(fp, style, off, sbp)
                while ((ch = getc(fp)) != EOF)
                        if (putchar(ch) == EOF)
                                oerr();
                while ((ch = getc(fp)) != EOF)
                        if (putchar(ch) == EOF)
                                oerr();
-               if (ferror(fp))
+               if (ferror(fp)) {
                        ierr();
                        ierr();
+                       return;
+               }
                (void)fflush(stdout);
                if (!fflag)
                        break;
                /* Sleep(3) is eight system calls.  Do it fast. */
                if (select(0, &zero, &zero, &zero, &second) == -1)
                (void)fflush(stdout);
                if (!fflag)
                        break;
                /* Sleep(3) is eight system calls.  Do it fast. */
                if (select(0, &zero, &zero, &zero, &second) == -1)
-                       err("select: %s", strerror(errno));
+                       err(1, "select: %s", strerror(errno));
                clearerr(fp);
        }
 }
                clearerr(fp);
        }
 }
@@ -158,8 +174,10 @@ rlines(fp, off, sbp)
                return;
 
        if ((p = mmap(NULL,
                return;
 
        if ((p = mmap(NULL,
-           size, PROT_READ, MAP_FILE, fileno(fp), (off_t)0)) == (caddr_t)-1)
-               err("%s", strerror(errno));
+           size, PROT_READ, MAP_FILE, fileno(fp), (off_t)0)) == (caddr_t)-1) {
+               err(0, "%s", strerror(errno));
+               return;
+       }
 
        /* Last char is special, ignore whether newline or not. */
        for (p += size - 1; --size;)
 
        /* Last char is special, ignore whether newline or not. */
        for (p += size - 1; --size;)
@@ -171,6 +189,8 @@ rlines(fp, off, sbp)
        /* Set the file pointer to reflect the length displayed. */
        size = sbp->st_size - size;
        WR(p, size);
        /* Set the file pointer to reflect the length displayed. */
        size = sbp->st_size - size;
        WR(p, size);
-       if (fseek(fp, sbp->st_size, SEEK_SET) == -1)
+       if (fseek(fp, sbp->st_size, SEEK_SET) == -1) {
                ierr();
                ierr();
+               return;
+       }
 }
 }
index 2704278..76a97ca 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)misc.c     5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)misc.c     5.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -24,13 +24,13 @@ static char sccsid[] = "@(#)misc.c  5.1 (Berkeley) %G%";
 void
 ierr()
 {
 void
 ierr()
 {
-       err("%s: %s", fname, strerror(errno));
+       err(0, "%s: %s", fname, strerror(errno));
 }
 
 void
 oerr()
 {
 }
 
 void
 oerr()
 {
-       err("stdout: %s", strerror(errno));
+       err(1, "stdout: %s", strerror(errno));
 }
 
 #if __STDC__
 }
 
 #if __STDC__
@@ -41,9 +41,10 @@ oerr()
 
 void
 #if __STDC__
 
 void
 #if __STDC__
-err(const char *fmt, ...)
+err(int fatal, const char *fmt, ...)
 #else
 #else
-err(fmt, va_alist)
+err(fatal, fmt, va_alist)
+       int fatal;
        char *fmt;
        va_dcl
 #endif
        char *fmt;
        va_dcl
 #endif
@@ -58,6 +59,7 @@ err(fmt, va_alist)
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
-       exit(1);
-       /* NOTREACHED */
+       if (fatal)
+               exit(1);
+       rval = 1;
 }
 }
index 7917b7a..663780b 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)read.c     5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)read.c     5.2 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -43,7 +43,7 @@ bytes(fp, off)
        char *sp;
 
        if ((sp = p = malloc(off)) == NULL)
        char *sp;
 
        if ((sp = p = malloc(off)) == NULL)
-               err("%s", strerror(errno));
+               err(1, "%s", strerror(errno));
 
        for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
                *p = ch;
 
        for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
                *p = ch;
@@ -52,8 +52,10 @@ bytes(fp, off)
                        p = sp;
                }
        }
                        p = sp;
                }
        }
-       if (ferror(fp))
+       if (ferror(fp)) {
                ierr();
                ierr();
+               return;
+       }
 
        if (rflag) {
                for (t = p - 1, len = 0; t >= sp; --t, ++len)
 
        if (rflag) {
                for (t = p - 1, len = 0; t >= sp; --t, ++len)
@@ -114,7 +116,7 @@ lines(fp, off)
        char *sp;
 
        if ((lines = malloc(off * sizeof(*lines))) == NULL)
        char *sp;
 
        if ((lines = malloc(off * sizeof(*lines))) == NULL)
-               err("%s", strerror(errno));
+               err(1, "%s", strerror(errno));
 
        sp = NULL;
        blen = cnt = recno = wrap = 0;
 
        sp = NULL;
        blen = cnt = recno = wrap = 0;
@@ -122,7 +124,7 @@ lines(fp, off)
        while ((ch = getc(fp)) != EOF) {
                if (++cnt > blen) {
                        if ((sp = realloc(sp, blen += 1024)) == NULL)
        while ((ch = getc(fp)) != EOF) {
                if (++cnt > blen) {
                        if ((sp = realloc(sp, blen += 1024)) == NULL)
-                               err("%s", strerror(errno));
+                               err(1, "%s", strerror(errno));
                        p = sp + cnt - 1;
                }
                *p++ = ch;
                        p = sp + cnt - 1;
                }
                *p++ = ch;
@@ -131,7 +133,7 @@ lines(fp, off)
                                lines[recno].blen = cnt + 256;
                                if ((lines[recno].l = realloc(lines[recno].l,
                                    lines[recno].blen)) == NULL)
                                lines[recno].blen = cnt + 256;
                                if ((lines[recno].l = realloc(lines[recno].l,
                                    lines[recno].blen)) == NULL)
-                                       err("%s", strerror(errno));
+                                       err(1, "%s", strerror(errno));
                        }
                        bcopy(sp, lines[recno].l, lines[recno].len = cnt);
                        cnt = 0;
                        }
                        bcopy(sp, lines[recno].l, lines[recno].len = cnt);
                        cnt = 0;
@@ -142,8 +144,10 @@ lines(fp, off)
                        }
                }
        }
                        }
                }
        }
-       if (ferror(fp))
+       if (ferror(fp)) {
                ierr();
                ierr();
+               return;
+       }
        if (cnt) {
                lines[recno].l = sp;
                lines[recno].len = cnt;
        if (cnt) {
                lines[recno].l = sp;
                lines[recno].len = cnt;
index ec7c743..8dfcffb 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)reverse.c  5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)reverse.c  5.4 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -88,9 +88,11 @@ r_reg(fp, style, off, sbp)
                return;
 
        fd = fileno(fp);
                return;
 
        fd = fileno(fp);
-       if ((p =
-           mmap(NULL, size, PROT_READ, MAP_FILE, fd, (off_t)0)) == (caddr_t)-1)
-               err("%s", strerror(errno));
+       if ((p = mmap(NULL,
+           size, PROT_READ, MAP_FILE, fd, (off_t)0)) == (caddr_t)-1) {
+               err(0, "%s", strerror(errno));
+               return;
+       }
        p += size - 1;
 
        if (style == RBYTES && off < size)
        p += size - 1;
 
        if (style == RBYTES && off < size)
@@ -146,7 +148,7 @@ r_buf(fp)
                if (enomem || (tl = malloc(sizeof(BF))) == NULL ||
                    (tl->l = malloc(BSZ)) == NULL) {
                        if (!mark)
                if (enomem || (tl = malloc(sizeof(BF))) == NULL ||
                    (tl->l = malloc(BSZ)) == NULL) {
                        if (!mark)
-                               err("%s", strerror(errno));
+                               err(1, "%s", strerror(errno));
                        tl = enomem ? tl->next : mark;
                        enomem += tl->len;
                } else if (mark) {
                        tl = enomem ? tl->next : mark;
                        enomem += tl->len;
                } else if (mark) {
index 7cbfa49..c7056cd 100644 (file)
@@ -6,7 +6,7 @@
 .\"
 .\" %sccs.include.redist.roff%
 .\"
 .\"
 .\" %sccs.include.redist.roff%
 .\"
-.\"    @(#)tail.1      6.8 (Berkeley) %G%
+.\"    @(#)tail.1      6.9 (Berkeley) %G%
 .\"
 .Dd 
 .Dt TAIL 1
 .\"
 .Dd 
 .Dt TAIL 1
@@ -22,7 +22,7 @@
 .Fl c Ar number |
 .Fl n Ar number
 .Oc
 .Fl c Ar number |
 .Fl n Ar number
 .Oc
-.Op Ar file
+.Op Ar file ...
 .Sh DESCRIPTION
 The
 .Nm tail
 .Sh DESCRIPTION
 The
 .Nm tail
@@ -64,7 +64,7 @@ to not stop when end of file is reached, but rather to wait for additional
 data to be appended to the input.
 The
 .Fl f
 data to be appended to the input.
 The
 .Fl f
-option is ignored on pipes but not on FIFO's.
+option is ignored if the standard input is a pipe, but not if it is a FIFO.
 .It Fl n Ar number
 The location is
 .Ar number
 .It Fl n Ar number
 The location is
 .Ar number
@@ -89,6 +89,13 @@ The default for the
 option is to display all of the input.
 .El
 .Pp
 option is to display all of the input.
 .El
 .Pp
+If more than a single file is specified, each file is preceded by a
+header consisting of the string
+.Dq ==> XXX <==
+where
+.Dq XXX
+is the name of the file.
+.Pp
 The
 .Nm tail
 utility exits 0 on success, and >0 if an error occurs.
 The
 .Nm tail
 utility exits 0 on success, and >0 if an error occurs.
index d9ba686..75af2c1 100644 (file)
@@ -15,7 +15,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)tail.c     5.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)tail.c     5.8 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -41,7 +41,7 @@ main(argc, argv)
        FILE *fp;
        long off;
        enum STYLE style;
        FILE *fp;
        long off;
        enum STYLE style;
-       int ch;
+       int ch, first;
        char *p;
 
        /*
        char *p;
 
        /*
@@ -61,7 +61,7 @@ main(argc, argv)
                usage(); \
        off = strtol(optarg, &p, 10) * (units); \
        if (*p) \
                usage(); \
        off = strtol(optarg, &p, 10) * (units); \
        if (*p) \
-               err("illegal offset -- %s", optarg); \
+               err(1, "illegal offset -- %s", optarg); \
        switch(optarg[0]) { \
        case '+': \
                if (off) \
        switch(optarg[0]) { \
        case '+': \
                if (off) \
@@ -129,30 +129,46 @@ main(argc, argv)
                        style = RLINES;
                }
 
                        style = RLINES;
                }
 
-       if (fname = *argv) {
-               if ((fp = fopen(fname, "r")) == NULL)
-                       ierr();
-       } else {
+       if (*argv)
+               for (first = 1; fname = *argv++;) {
+                       if ((fp = fopen(fname, "r")) == NULL) {
+                               ierr();
+                               continue;
+                       }
+                       if (argc > 1) {
+                               (void)printf("%s==> %s <==\n",
+                                   first ? "" : "\n", fname);
+                               first = 0;
+                       }
+
+                       if (rflag)
+                               reverse(fp, style, off, &sb);
+                       else
+                               forward(fp, style, off, &sb);
+               }
+       else {
                fp = stdin;
                fname = "stdin";
                fp = stdin;
                fname = "stdin";
-       }
 
 
-       if (fstat(fileno(fp), &sb))
-               ierr();
+               if (fstat(fileno(fp), &sb)) {
+                       ierr();
+                       exit(1);
+               }
 
 
-       /*
-        * Determine if input is a pipe.  4.4BSD will set the SOCKET
-        * bit in the st_mode field for pipes.  Fix this then.
-        */
-       if (lseek(fileno(fp), 0L, SEEK_CUR) == -1 && errno == ESPIPE) {
-               errno = 0;
-               fflag = 0;              /* POSIX.2 requires this. */
-       }
+               /*
+                * Determine if input is a pipe.  4.4BSD will set the SOCKET
+                * bit in the st_mode field for pipes.  Fix this then.
+                */
+               if (lseek(fileno(fp), 0L, SEEK_CUR) == -1 && errno == ESPIPE) {
+                       errno = 0;
+                       fflag = 0;              /* POSIX.2 requires this. */
+               }
 
 
-       if (rflag)
-               reverse(fp, style, off, &sb);
-       else
-               forward(fp, style, off, &sb);
+               if (rflag)
+                       reverse(fp, style, off, &sb);
+               else
+                       forward(fp, style, off, &sb);
+       }
        exit(rval);
 }
 
        exit(rval);
 }
 
@@ -185,7 +201,7 @@ obsolete(argv)
                        /* Malloc space for dash, new option and argument. */
                        len = strlen(*argv);
                        if ((start = p = malloc(len + 3)) == NULL)
                        /* Malloc space for dash, new option and argument. */
                        len = strlen(*argv);
                        if ((start = p = malloc(len + 3)) == NULL)
-                               err("%s", strerror(errno));
+                               err(1, "%s", strerror(errno));
                        *p++ = '-';
 
                        /*
                        *p++ = '-';
 
                        /*
@@ -215,7 +231,7 @@ obsolete(argv)
                                *p++ = 'n';
                                break;
                        default:
                                *p++ = 'n';
                                break;
                        default:
-                               err("illegal option -- %s", *argv);
+                               err(1, "illegal option -- %s", *argv);
                        }
                        *p++ = *argv[0];
                        (void)strcpy(p, ap);
                        }
                        *p++ = *argv[0];
                        (void)strcpy(p, ap);