make tail match historic practice for the various arguments
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Thu, 13 Feb 1992 07:50:37 +0000 (23:50 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Thu, 13 Feb 1992 07:50:37 +0000 (23:50 -0800)
SCCS-vsn: usr.bin/tail/tail.c 5.7
SCCS-vsn: usr.bin/tail/tail.1 6.8

usr/src/usr.bin/tail/tail.1
usr/src/usr.bin/tail/tail.c

index 9d6ef6f..7cbfa49 100644 (file)
@@ -6,7 +6,7 @@
 .\"
 .\" %sccs.include.redist.roff%
 .\"
 .\"
 .\" %sccs.include.redist.roff%
 .\"
-.\"    @(#)tail.1      6.7 (Berkeley) %G%
+.\"    @(#)tail.1      6.8 (Berkeley) %G%
 .\"
 .Dd 
 .Dt TAIL 1
 .\"
 .Dd 
 .Dt TAIL 1
@@ -30,26 +30,29 @@ utility displays the contents of
 .Ar file
 or, by default, its standard input, to the standard output.
 .Pp
 .Ar file
 or, by default, its standard input, to the standard output.
 .Pp
-The display begins at an offset from either the beginning or end
-of the input.
-Offsets may be specified in terms of bytes, lines or 512-byte blocks.
+The display begins at a byte, line or 512-byte block location in the
+input.
 Numbers having a leading plus (``+'') sign are relative to the beginning
 Numbers having a leading plus (``+'') sign are relative to the beginning
-of the input.
+of the input, for example,
+.Dq -c +2
+starts the display at the second
+byte of the input.
 Numbers having a leading minus (``-'') sign or no explicit sign are
 Numbers having a leading minus (``-'') sign or no explicit sign are
-relative to the end of the input.
-All offsets are 1 based, i.e. ``-c +1'' skips a single byte of the
-input.
-The default offset is ``-n 10'', or 10 lines from the end of the
-input.
+relative to the end of the input, for example,
+.Dq -n 2
+displays the last two lines of the input.
+The default starting location is
+.Dq -n 10 ,
+or the last 10 lines of the input.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl b Ar number
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl b Ar number
-The offset is
+The location is
 .Ar number
 512-byte blocks.
 .It Fl c Ar number
 .Ar number
 512-byte blocks.
 .It Fl c Ar number
-The offset is
+The location is
 .Ar number
 bytes.
 .It Fl f
 .Ar number
 bytes.
 .It Fl f
@@ -63,7 +66,7 @@ The
 .Fl f
 option is ignored on pipes but not on FIFO's.
 .It Fl n Ar number
 .Fl f
 option is ignored on pipes but not on FIFO's.
 .It Fl n Ar number
-The offset is
+The location is
 .Ar number
 lines.
 .It Fl r
 .Ar number
 lines.
 .It Fl r
@@ -99,8 +102,29 @@ The
 utility is expected to be a superset of the POSIX 1003.2
 specification.
 In particular, the
 utility is expected to be a superset of the POSIX 1003.2
 specification.
 In particular, the
+.Fl b
+and
+.Fl r
+options are extensions to that standard.
+.Pp
+The historic command line syntax of
+.Nm tail
+is supported by this implementation.
+The only difference between this implementation and historic versions
+of
+.Nm tail ,
+once the command line syntax translation has been done, is that the
+.Fl b ,
+.Fl c
+and
+.Fl n
+options modify the
 .Fl r
 .Fl r
-option is an extension to that standard.
+option, i.e. ``-r -c 4'' displays the last 4 characters of the last line
+of the input, while the historic tail (using the historic syntax ``-4cr'')
+would ignore the
+.Fl c
+option and display the last 4 lines of the input.
 .Sh HISTORY
 A
 .Nm tail
 .Sh HISTORY
 A
 .Nm tail
index 9a79768..d9ba686 100644 (file)
@@ -15,7 +15,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)tail.c     5.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)tail.c     5.7 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -42,39 +42,56 @@ main(argc, argv)
        long off;
        enum STYLE style;
        int ch;
        long off;
        enum STYLE style;
        int ch;
-       char *p, *num;
+       char *p;
 
 
-       obsolete(argv);
+       /*
+        * Tail's options are weird.  First, -n10 is the same as -n-10, not
+        * -n+10.  Second, the number options are 1 based and not offsets,
+        * so -n+1 is the first line, and -c-1 is the last byte.  Third, the
+        * number options for the -r option specify the number of things that
+        * get displayed, not the starting point in the file.  The one major
+        * incompatibility in this version as compared to historical versions
+        * is that the 'r' option couldn't be modified by the -lbc options,
+        * i.e. it was always done in lines.  This version treats -rc as a
+        * number of characters in reverse order.  Finally, the default for
+        * -r is the entire file, not 10 lines.
+        */
+#define        ARG(units, forward, backward) { \
+       if (style) \
+               usage(); \
+       off = strtol(optarg, &p, 10) * (units); \
+       if (*p) \
+               err("illegal offset -- %s", optarg); \
+       switch(optarg[0]) { \
+       case '+': \
+               if (off) \
+                       off -= (units); \
+                       style = (forward); \
+               break; \
+       case '-': \
+               off = -off; \
+               /* FALLTHROUGH */ \
+       default: \
+               style = (backward); \
+               break; \
+       } \
+}
 
 
+       obsolete(argv);
        style = NOTSET;
        while ((ch = getopt(argc, argv, "b:c:fn:r")) != EOF)
                switch(ch) {
                case 'b':
        style = NOTSET;
        while ((ch = getopt(argc, argv, "b:c:fn:r")) != EOF)
                switch(ch) {
                case 'b':
-                       if (style)
-                               usage();
-                       off = strtol(num = optarg, &p, 10) * 512;
-                       if (*p)
-                               err("illegal offset -- %s", optarg);
-                       style = *num == '+' ? FBYTES : RBYTES;
+                       ARG(512, FBYTES, RBYTES);
                        break;
                case 'c':
                        break;
                case 'c':
-                       if (style)
-                               usage();
-                       off = strtol(num = optarg, &p, 10);
-                       if (*p)
-                               err("illegal offset -- %s", optarg);
-                       style = *num == '+' ? FBYTES : RBYTES;
+                       ARG(1, FBYTES, RBYTES);
                        break;
                case 'f':
                        fflag = 1;
                        break;
                case 'n':
                        break;
                case 'f':
                        fflag = 1;
                        break;
                case 'n':
-                       if (style)
-                               usage();
-                       off = strtol(num = optarg, &p, 10);
-                       if (*p)
-                               err("illegal offset -- %s", optarg);
-                       style = *num == '+' ? FLINES : RLINES;
+                       ARG(1, FLINES, RLINES);
                        break;
                case 'r':
                        rflag = 1;
                        break;
                case 'r':
                        rflag = 1;
@@ -87,20 +104,31 @@ main(argc, argv)
        argv += optind;
 
        /*
        argv += optind;
 
        /*
-        * Don't permit follow option if displaying in reverse.  An offset
-        * with an explicit leading minus is meaningless.
+        * If displaying in reverse, don't permit follow option, and convert
+        * style values.
         */
        if (rflag) {
                if (fflag)
                        usage();
         */
        if (rflag) {
                if (fflag)
                        usage();
-               if (style && *num == '-')
-                       err("illegal offset for -r option -- %s", num);
                if (style == FBYTES)
                        style = RBYTES;
                if (style == FLINES)
                        style = RLINES;
        }
 
                if (style == FBYTES)
                        style = RBYTES;
                if (style == FLINES)
                        style = RLINES;
        }
 
+       /*
+        * If style not specified, the default is the whole file for -r, and
+        * the last 10 lines if not -r.
+        */
+       if (style == NOTSET)
+               if (rflag) {
+                       off = 0;
+                       style = REVERSE;
+               } else {
+                       off = 10;
+                       style = RLINES;
+               }
+
        if (fname = *argv) {
                if ((fp = fopen(fname, "r")) == NULL)
                        ierr();
        if (fname = *argv) {
                if ((fp = fopen(fname, "r")) == NULL)
                        ierr();
@@ -121,24 +149,6 @@ main(argc, argv)
                fflag = 0;              /* POSIX.2 requires this. */
        }
 
                fflag = 0;              /* POSIX.2 requires this. */
        }
 
-       /*
-        * Tail's options are weird.  First, -n10 is the same as -n-10, not
-        * -n+10.  Second, the number options for the -r option specify the
-        * number of bytes/chars/lines that get displayed, not the offset from
-        * the beginning/end of the file.  Finally, the default for -r is the
-        * entire file, not 10 lines.
-        */
-       if (!style)
-               if (rflag) {
-                       off = 0;
-                       style = REVERSE;
-               } else {
-                       off = 10;
-                       style = RLINES;
-               }
-       else if (off < 0)
-               off = -off;
-
        if (rflag)
                reverse(fp, style, off, &sb);
        else
        if (rflag)
                reverse(fp, style, off, &sb);
        else