bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

backward-compatibility fixes for "tail"


From: Paul Eggert
Subject: backward-compatibility fixes for "tail"
Date: Thu, 23 Sep 2004 13:39:57 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

My previous changes to "tail" were too drastic: they removed support
for some traditional usage that is not in POSIX 1003.2-1992 but is in
SUSv2 or in older GNU "tail".  I installed the following patch as
penance.  It makes "tail" a bit more generous about what it supports,
though "tail -10" still is rejected when in POSIX 1003.1-2001 mode
pending resolution of this issue at the Open Group level.

2004-09-23  Paul Eggert  <address@hidden>

        * doc/coreutils.texi (tail invocation): Fix bugs in the description of
        the obsolete syntax (e.g., it does not support -k or -m).  Warn
        about usages like "tail -" and "tail -c 4" that are ambigous on
        older systems.
        * src/tail.c (parse_obsolete_option): Bring back support
        for obsolete option followed by non-obsolete, or by more
        than one file.  When obsolete, conform to SUSv2 rather than
        original POSIX 1003.2-1992, as SUSv2 corrected the case of
        "tail -c".  Add support for the SUSv2 "b" modifier.
        * NEWS: Mention the above.
        * tests/tail/Test.pm: New test case obs-b to check the above.
        err-[134] no longer need _POSIX2_VERSION=199209.
        Fix comments to match revised behavior.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.236
diff -p -u -r1.236 NEWS
--- NEWS        21 Sep 2004 22:00:27 -0000      1.236
+++ NEWS        23 Sep 2004 20:23:49 -0000
@@ -101,10 +101,11 @@ GNU coreutils NEWS                      
 
   "tail -f" no longer mishandles pipes and fifos.  With no operands,
   tail now ignores -f if standard input is a pipe, as POSIX requires.
-  When conforming to POSIX 1003.2-1992, tail now handles some obscure
-  cases more correctly, e.g., "tail +cl file" now reads the file "+cl"
-  rather than reporting an error, and "tail - file" no longer reads
-  standard input.
+  When conforming to POSIX 1003.2-1992, tail now supports the SUSv2 b
+  modifier (e.g., "tail -10b file") and it handles some obscure cases
+  more correctly, e.g., "tail +cl" now reads the file "+cl" rather
+  than reporting an error, "tail -c file" no longer reports an error,
+  and "tail - file" no longer reads standard input.
 
   tee now exits when it gets a SIGPIPE signal, as POSIX requires.
   To get tee's old behavior, use the shell command "(trap '' PIPE; tee)".
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.213
diff -p -u -r1.213 coreutils.texi
--- doc/coreutils.texi  21 Sep 2004 05:56:11 -0000      1.213
+++ doc/coreutils.texi  23 Sep 2004 20:23:53 -0000
@@ -2552,15 +2552,20 @@ Always print file name headers.
 @end table
 
 On older systems, @command{tail} supports an obsolete option
address@hidden@address@hidden, which is recognized only if it is
-specified first.  @var{count} is a decimal number optionally followed
-by a size letter (@samp{b}, @samp{k}, @samp{m}) as in @option{-c}, or
address@hidden to mean count by lines, or other option letters
-(@samp{cfqv}).  Some older @command{tail} implementations also support
-an obsolete option @address@hidden with the same meaning as
address@hidden@var{count}}.  @acronym{POSIX} 1003.1-2001 (@pxref{Standards
-conformance}) does not allow these options; use @option{-c
address@hidden or @option{-n @var{count}} instead.
address@hidden@var{count}[bcl][f]}, which is recognized only if it is
+specified first.  @var{count} is an optional decimal number optionally
+followed by a size letter (@samp{b}, @samp{c}, @samp{l}) to mean count
+by 512-byte blocks, bytes, or lines, optionally followed by @samp{f}
+which has the same meaning as @option{-f}.  Also, the leading @samp{-}
+can be replaced by @samp{+} with the same meaning as in counts.
address@hidden 1003.1-2001 (@pxref{Standards conformance}) does not
+allow most of these obsolete usages; use @option{-c @var{count}[b]},
address@hidden @var{count}}, and/or @option{-f} instead.
+
+On older systems, obsolete usage overrides normal usage, so portable
+shell scripts should avoid commands that can be interpreted either
+way.  For example, use @samp{tail -- - file} rather than @samp{tail -
+file}, and use @samp{tail -c4} rather than @samp{tail -c 4}.
 
 @exitstatus
 
Index: src/tail.c
===================================================================
RCS file: /fetish/cu/src/tail.c,v
retrieving revision 1.228
diff -p -u -r1.228 tail.c
--- src/tail.c  21 Sep 2004 22:26:42 -0000      1.228
+++ src/tail.c  23 Sep 2004 20:23:54 -0000
@@ -1375,14 +1375,15 @@ parse_obsolete_option (int argc, char * 
   const char *n_string;
   const char *n_string_end;
   bool obsolete_usage;
+  int default_count = DEFAULT_N_LINES;
   bool t_from_start;
   bool t_count_lines = true;
   bool t_forever = false;
-  int len;
 
   /* With the obsolete form, there is one option string and
-     at most one file argument, possibly preceded by "--".  */
-  if (! ((2 <= argc && argc <= 3) || (argc == 4 && STREQ (argv[2], "--"))))
+     (technically) at most one file argument.  But we allow two or more
+     by default.  */
+  if (argc < 2)
     return false;
 
   obsolete_usage = (posix2_version () < 200112);
@@ -1401,14 +1402,11 @@ parse_obsolete_option (int argc, char * 
       break;
 
     case '-':
-      /* Plain "-" is standard input in the non-obsolete form.  */
-      if (!obsolete_usage && !*p)
-       return false;
-
-      /* Plain "-c" is required to be the non-obsolete option.  For
-         plain "-f" POSIX 1003.2-1992 is ambiguous; assume the
-         non-obsolete form.  */
-      if ((p[0] == 'c' || p[0] == 'f') && !p[1])
+      /* In the non-obsolete form, "-" is standard input and "-c"
+        requires an option-argument.  The obsolete multidigit options
+        are diagnosed more nicely below than they would be if we
+        simply returned false here.  */
+      if (!obsolete_usage && !p[p[0] == 'c'])
        return false;
 
       t_from_start = false;
@@ -1422,6 +1420,7 @@ parse_obsolete_option (int argc, char * 
 
   switch (*p)
     {
+    case 'b': default_count *= 512;    /* Fall through.  */
     case 'c': t_count_lines = false;   /* Fall through.  */
     case 'l': p++; break;
     }
@@ -1435,24 +1434,22 @@ parse_obsolete_option (int argc, char * 
   if (*p)
     return false;
 
-  len = n_string_end - n_string;
-
   if (n_string == n_string_end)
-    *n_units = DEFAULT_N_LINES;
-  else if (xstrtoumax (n_string, NULL, 10, n_units, NULL) != LONGINT_OK)
-    error (EXIT_FAILURE, 0, _("number `%.*s' too large"), len, n_string);
-
-  if (!obsolete_usage)
+    *n_units = default_count;
+  else
     {
-      if (len == 0)
+      if ((xstrtoumax (n_string, NULL, 10, n_units, "b")
+          & ~LONGINT_INVALID_SUFFIX_CHAR)
+         != LONGINT_OK)
+       error (EXIT_FAILURE, 0, _("number in `%s' is too large"), argv[1]);
+
+      if (!obsolete_usage)
        {
-         len = 2;
-         n_string = "10";
+         error (0, 0, _("`%s' option is obsolete; use `%s-%c %"PRIuMAX"'"),
+                argv[1], t_forever ? "-f " : "", t_count_lines ? 'n' : 'c',
+                *n_units);
+         usage (EXIT_FAILURE);
        }
-      error (0, 0, _("`%s' option is obsolete; use `%s-%c %.*s'"),
-            argv[1], t_forever ? "-f " : "", t_count_lines ? 'n' : 'c',
-            len, n_string);
-      usage (EXIT_FAILURE);
     }
 
   /* Set globals.  */
@@ -1470,9 +1467,6 @@ parse_options (int argc, char **argv,
 {
   int c;
 
-  count_lines = true;
-  forever = from_start = print_headers = false;
-
   while ((c = getopt_long (argc, argv, "c:n:fFqs:v", long_options, NULL))
         != -1)
     {
@@ -1606,6 +1600,7 @@ main (int argc, char **argv)
   char **file;
   struct File_spec *F;
   int i;
+  bool obsolete_option;
 
   /* The number of seconds to sleep between iterations.
      During one iteration, every file name or descriptor is checked to
@@ -1622,10 +1617,12 @@ main (int argc, char **argv)
 
   have_read_stdin = false;
 
-  if (parse_obsolete_option (argc, argv, &n_units))
-    optind = 2;
-  else
-    parse_options (argc, argv, &n_units, &header_mode, &sleep_interval);
+  count_lines = true;
+  forever = from_start = print_headers = false;
+  obsolete_option = parse_obsolete_option (argc, argv, &n_units);
+  argc -= obsolete_option;
+  argv += obsolete_option;
+  parse_options (argc, argv, &n_units, &header_mode, &sleep_interval);
 
   /* To start printing with item N_UNITS from the start of the file, skip
      N_UNITS - 1 items.  `tail -n +0' is actually meaningless, but for Unix
Index: tests/tail/Test.pm
===================================================================
RCS file: /fetish/cu/tests/tail/Test.pm,v
retrieving revision 1.13
diff -p -u -r1.13 Test.pm
--- tests/tail/Test.pm  10 Sep 2004 20:54:32 -0000      1.13
+++ tests/tail/Test.pm  23 Sep 2004 20:23:55 -0000
@@ -32,21 +32,25 @@ my @tv = (
 # With no number, this is like -10l
 ['obs-l', '-l', "x\n" . ("y\n" x 10) . 'z', ("y\n" x 9) . 'z', 0],
 
-# This should get `tail: +cl: No such file or directory'
+['obs-b', '-b', "x\n" x (512 * 10 / 2 + 1), "x\n" x (512 * 10 / 2), 0],
+
+# This should get
+# `tail: cannot open `+cl' for reading: No such file or directory'
 ['err-1', '+cl', '', '', 1],
 
 # This should get `tail: l: invalid number of bytes'
 ['err-2', '-cl', '', '', 1],
 
-# This should get `tail: z: invalid suffix character in obsolescent option'
+# This should get
+# `tail: cannot open `+2cz' for reading: No such file or directory'
 ['err-3', '+2cz', '', '', 1],
 
-# This should get `tail: X: invalid suffix character in obsolescent option'
+# This should get `tail: invalid option -- 2'
 ['err-4', '-2cX', '', '', 1],
 
 # Since the number is larger than 2^64, this should provoke
-# the diagnostic: `tail: 99999999999999999999: number of bytes is so large \
-# that it is not representable' on all systems... probably, for now, maybe.
+# the diagnostic: `tail: 99999999999999999999: invalid number of bytes'
+# on all systems... probably, for now, maybe.
 ['err-5', '-c99999999999999999999', '', '', 1],
 ['err-6', '-c', '', '', 1],
 
@@ -79,7 +83,7 @@ sub test_vector
     {
       my ($test_name, $flags, $in, $exp, $ret) = @$t;
 
-      $test_name =~ /^(obs|err-[134]|minus-)/
+      $test_name =~ /^(obs|minus-)/
        and $Test::env{$test_name} = ['_POSIX2_VERSION=199209'];
 
       # If you run the minus* tests with a FILE arg they'd hang.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]