[Top][All Lists]
[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.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- backward-compatibility fixes for "tail",
Paul Eggert <=