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 <[EMAIL PROTECTED]> * 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 [EMAIL PROTECTED]@[EMAIL PROTECTED], 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 [EMAIL PROTECTED] to mean count by lines, or other option letters -(@samp{cfqv}). Some older @command{tail} implementations also support -an obsolete option @[EMAIL PROTECTED] with the same meaning as [EMAIL PROTECTED]@var{count}}. @acronym{POSIX} 1003.1-2001 (@pxref{Standards -conformance}) does not allow these options; use @option{-c [EMAIL PROTECTED] or @option{-n @var{count}} instead. [EMAIL PROTECTED]@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. [EMAIL PROTECTED] 1003.1-2001 (@pxref{Standards conformance}) does not +allow most of these obsolete usages; use @option{-c @var{count}[b]}, [EMAIL PROTECTED] @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. _______________________________________________ Bug-coreutils mailing list [EMAIL PROTECTED] http://lists.gnu.org/mailman/listinfo/bug-coreutils