From 9bc2b6e88474a8ebb50c94f29320d343bd374928 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Apr 2023 14:33:20 +0200 Subject: seq: accept negative parameters function old new delta seq_main 429 476 +47 packed_usage 34557 34538 -19 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 47/-19) Total: 28 bytes Signed-off-by: Denys Vlasenko --- coreutils/seq.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'coreutils') diff --git a/coreutils/seq.c b/coreutils/seq.c index beb339d1e..c0e2d1e06 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -22,7 +22,7 @@ //usage:#define seq_full_usage "\n\n" //usage: "Print numbers from FIRST to LAST, in steps of INC.\n" //usage: "FIRST, INC default to 1.\n" -//usage: "\n -w Pad to last with leading zeros" +//usage: "\n -w Pad with leading zeros" //usage: "\n -s SEP String separator" #include "libbb.h" @@ -41,6 +41,7 @@ int seq_main(int argc, char **argv) unsigned width; unsigned frac_part; const char *sep, *opt_s = "\n"; + char *saved; unsigned opt; #if ENABLE_LOCALE_SUPPORT @@ -49,7 +50,25 @@ int seq_main(int argc, char **argv) setlocale(LC_NUMERIC, "C"); #endif - opt = getopt32(argv, "+ws:", &opt_s); + /* Cater for negative arguments: if we see one, truncate argv[] on it */ + n = 0; + for (;;) { + char c; + saved = argv[++n]; + if (!saved) + break; + if (saved[0] != '-') + break; + c = saved[1]; + if (c == '.' || (c >= '0' && c <= '9')) { + argv[n] = NULL; + break; + } + } + opt = getopt32(argv, "+ws:", &opt_s); /* "+": stop at first non-option */ + /* Restore possibly truncated argv[] */ + argv[n] = saved; + argc -= optind; argv += optind; first = increment = 1; -- cgit v1.2.3-55-g6feb From 478b5ac2bcdb5014d8e6a6e8d7647b4c599cc1a7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Apr 2023 20:29:59 +0200 Subject: seq: fix yet another case of negative parameters not working Signed-off-by: Denys Vlasenko --- coreutils/seq.c | 8 ++++++-- testsuite/seq.tests | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'coreutils') diff --git a/coreutils/seq.c b/coreutils/seq.c index c0e2d1e06..77a8aba8a 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -57,8 +57,12 @@ int seq_main(int argc, char **argv) saved = argv[++n]; if (!saved) break; - if (saved[0] != '-') - break; + if (saved[0] != '-') { + // break; // "seq -s : -1 1" won't be treated correctly + continue; + } +// "seq -s -1 1 9" is not treated correctly, but such usage +// (delimiter string which looks like negative number) is very unlikely c = saved[1]; if (c == '.' || (c >= '0' && c <= '9')) { argv[n] = NULL; diff --git a/testsuite/seq.tests b/testsuite/seq.tests index d414169c9..d0da8c119 100755 --- a/testsuite/seq.tests +++ b/testsuite/seq.tests @@ -45,5 +45,6 @@ testing "seq count by .3 with padding 2" "seq -w 03 .3 0004" "0003.0\n0003.3\n00 testing "seq from -4 count down by 2" "seq -4 -2 -8" "-4\n-6\n-8\n" "" "" testing "seq from -.0 count down by .25" "seq -.0 -.25 -.9" "-0.00\n-0.25\n-0.50\n-0.75\n" "" "" +testing "seq -s : with negative start" "seq -s : -1 1" "-1:0:1\n" "" "" exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 550e6d8fbd05ea0ab60ff3e542327efb4e9cc254 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Apr 2023 12:23:36 +0200 Subject: sleep: fix error exit when called as "sh" builtin Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'coreutils') diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 667db558d..a0cee5a4a 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -74,7 +74,8 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) ++argv; if (!*argv) { /* Without this, bare "sleep" in ash shows _ash_ --help */ - if (ENABLE_ASH_SLEEP && applet_name[0] != 's') { + /* (ash can be the "sh" applet as well, so check 2nd char) */ + if (ENABLE_ASH_SLEEP && applet_name[1] != 'l') { bb_simple_error_msg("sleep: missing operand"); return EXIT_FAILURE; } -- cgit v1.2.3-55-g6feb From 238dab322a630b493843a6bdf3203e93db87469a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Apr 2023 14:47:24 +0200 Subject: shuf: add (disabled) code to support very long numbers in -i LO-HI Signed-off-by: Denys Vlasenko --- coreutils/shuf.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 6 deletions(-) (limited to 'coreutils') diff --git a/coreutils/shuf.c b/coreutils/shuf.c index 337366b45..fe0358e07 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -66,6 +66,12 @@ static void shuffle_lines(char **lines, unsigned numlines, unsigned outlines) } } +/* We can handle insanity like this: + * shuf -i 3333333333333333333333333333333333333333333333333333333333333123456789001-3333333333333333333333333333333333333333333333333333333333333123456789019 + * but do we want to have +200 bytes of code (~40% code growth)? + */ +#define COMMON_PREFIX_HACK 0 + int shuf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int shuf_main(int argc, char **argv) { @@ -76,6 +82,11 @@ int shuf_main(int argc, char **argv) unsigned numlines, outlines; unsigned i; char eol; +#if COMMON_PREFIX_HACK + unsigned pfx_len = 0; + unsigned padding_width = padding_width; + const char *pfx = pfx; +#endif opts = getopt32(argv, "^" OPT_STR @@ -104,10 +115,46 @@ int shuf_main(int argc, char **argv) if (!dash) { bb_error_msg_and_die("bad range '%s'", opt_i_str); } - *dash = '\0'; + *dash++ = '\0'; +#if COMMON_PREFIX_HACK + { + const char *a = opt_i_str; + const char *b = dash; + /* Skip leading zeros (they may mask that common prefix does exist) */ + while (*a == '0') a++; + while (*b == '0') b++; + /* Do we have a common prefix (long enough to bother)? */ + padding_width = strlen(a); + if (padding_width > 5 && padding_width == strlen(b)) { + /* How long is it? */ + pfx = a; + while (isdigit(*a) && *a == *b) { + a++; + b++; + } + if (*a == '\0') { + /* "123456-123456", and we 'ate' all of them */ + /* prevent trying to xatoull("") */ + a--; + b--; + } + pfx_len = a - opt_i_str; /* can end up being 0 */ + padding_width -= pfx_len; + lo = xatoull(a); + hi = xatoull(b); + } else { + /* Undo leading zero 'eating' (think "0-9") */ + a = opt_i_str; + b = dash; + } + lo = xatoull(a); + hi = xatoull(b); + } +#else lo = xatoull(opt_i_str); - hi = xatoull(dash + 1); - *dash = '-'; + hi = xatoull(dash); +#endif + dash[-1] = '-'; if (hi < lo) bb_error_msg_and_die("bad range '%s'", opt_i_str); hi -= lo; @@ -165,9 +212,14 @@ int shuf_main(int argc, char **argv) eol = '\0'; for (i = numlines - outlines; i < numlines; i++) { - if (opts & OPT_i) - printf("%llu%c", lo + (uintptr_t)lines[i], eol); - else + if (opts & OPT_i) { +#if COMMON_PREFIX_HACK + if (pfx_len != 0) + printf("%.*s%0*llu%c", pfx_len, pfx, padding_width, lo + (uintptr_t)lines[i], eol); + else +#endif + printf("%llu%c", lo + (uintptr_t)lines[i], eol); + } else printf("%s%c", lines[i], eol); } -- cgit v1.2.3-55-g6feb From 8696f5d380209e6aba13ffc52eced9239510b275 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Apr 2023 14:51:11 +0200 Subject: shuf: remove redundant code Signed-off-by: Denys Vlasenko --- coreutils/shuf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'coreutils') diff --git a/coreutils/shuf.c b/coreutils/shuf.c index fe0358e07..3483a289b 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -140,8 +140,6 @@ int shuf_main(int argc, char **argv) } pfx_len = a - opt_i_str; /* can end up being 0 */ padding_width -= pfx_len; - lo = xatoull(a); - hi = xatoull(b); } else { /* Undo leading zero 'eating' (think "0-9") */ a = opt_i_str; -- cgit v1.2.3-55-g6feb From f7065aa9ae54ce0d1772fd2e6f0e0b6862a50b71 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Apr 2023 14:56:05 +0200 Subject: shuf: fix pfx_len calculation Signed-off-by: Denys Vlasenko --- coreutils/shuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'coreutils') diff --git a/coreutils/shuf.c b/coreutils/shuf.c index 3483a289b..107899a10 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -138,7 +138,7 @@ int shuf_main(int argc, char **argv) a--; b--; } - pfx_len = a - opt_i_str; /* can end up being 0 */ + pfx_len = a - pfx; /* can end up being 0 */ padding_width -= pfx_len; } else { /* Undo leading zero 'eating' (think "0-9") */ -- cgit v1.2.3-55-g6feb From 8b72877babb20be9bb46c4437f5e1870390c29cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Apr 2023 00:10:10 +0200 Subject: shuf: another tweak to COMMON_PREFIX_HACK code Signed-off-by: Denys Vlasenko --- coreutils/shuf.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'coreutils') diff --git a/coreutils/shuf.c b/coreutils/shuf.c index 107899a10..466969745 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -67,7 +67,7 @@ static void shuffle_lines(char **lines, unsigned numlines, unsigned outlines) } /* We can handle insanity like this: - * shuf -i 3333333333333333333333333333333333333333333333333333333333333123456789001-3333333333333333333333333333333333333333333333333333333333333123456789019 + * shuf -i 333333333333333333333333333333001-333333333333333333333333333333019 * but do we want to have +200 bytes of code (~40% code growth)? */ #define COMMON_PREFIX_HACK 0 @@ -128,16 +128,12 @@ int shuf_main(int argc, char **argv) if (padding_width > 5 && padding_width == strlen(b)) { /* How long is it? */ pfx = a; - while (isdigit(*a) && *a == *b) { + while (isdigit(*a) && *a == *b + && a[1] /* "111111-111111" case: avoid xatoull("") */ + ) { a++; b++; } - if (*a == '\0') { - /* "123456-123456", and we 'ate' all of them */ - /* prevent trying to xatoull("") */ - a--; - b--; - } pfx_len = a - pfx; /* can end up being 0 */ padding_width -= pfx_len; } else { -- cgit v1.2.3-55-g6feb From 2ffd8986e21f1782c78e1a9d34f6042af53d876c Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 16 Apr 2023 08:23:58 +0100 Subject: tr: display usage for incorrect arguments tr must have one or two non-option arguments. Display the usage message if any other number is present. function old new delta .rodata 108389 108392 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 3/0) Total: 3 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- coreutils/tr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'coreutils') diff --git a/coreutils/tr.c b/coreutils/tr.c index 1e402dfdb..7fe7f89d5 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -299,7 +299,7 @@ int tr_main(int argc UNUSED_PARAM, char **argv) */ /* '+': stop at first non-option */ - opts = getopt32(argv, "^+" "Ccds" "\0" "-1"); + opts = getopt32(argv, "^+" "Ccds" "\0" "-1:?2"); argv += optind; str1_length = expand(*argv++, &str1); -- cgit v1.2.3-55-g6feb From d2b81b3dc2b31d32e1060d3ea8bd998d30a37d8a Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 24 Mar 2023 09:58:14 -0500 Subject: readlink: support --, -n always POSIX will be standardizing readlink (just the -n option) and realpath (just -E and -e options): https://www.austingroupbugs.net/view.php?id=1457 Change things for readlink so that the POSIX-mandated -n and -- work even when disabling the non-standard (and partially non-working) -f when FEATURE_READLINK_FOLLOW is clear. POSIX also wants readlink to be verbose by default (if the argument is not a symlink, readlink must output a diagnostic); I did NOT address that one, because I'm waiting to see what the GNU Coreutils folks do: https://lists.gnu.org/archive/html/bug-coreutils/2023-03/msg00035.html Partial fix for https://bugs.busybox.net/show_bug.cgi?id=15466 function old new delta packed_usage 34538 34557 +19 Signed-off-by: Eric Blake Signed-off-by: Denys Vlasenko --- coreutils/readlink.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'coreutils') diff --git a/coreutils/readlink.c b/coreutils/readlink.c index b2e867883..0a9aa957e 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -25,12 +25,14 @@ //kbuild:lib-$(CONFIG_READLINK) += readlink.o //usage:#define readlink_trivial_usage -//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE" +//usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") +//usage: IF_NOT_FEATURE_READLINK_FOLLOW("[-n] ") +//usage: "FILE" //usage:#define readlink_full_usage "\n\n" -//usage: "Display the value of a symlink" -//usage: IF_FEATURE_READLINK_FOLLOW( "\n" -//usage: "\n -f Canonicalize by following all symlinks" +//usage: "Display the value of a symlink" "\n" //usage: "\n -n Don't add newline" +//usage: IF_FEATURE_READLINK_FOLLOW( +//usage: "\n -f Canonicalize by following all symlinks" //usage: "\n -v Verbose" //usage: ) @@ -67,25 +69,18 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) { char *buf; char *fname; + unsigned opt; - IF_FEATURE_READLINK_FOLLOW( - unsigned opt; - /* We need exactly one non-option argument. */ - opt = getopt32(argv, "^" "fnvsq" "\0" "=1"); - fname = argv[optind]; - ) - IF_NOT_FEATURE_READLINK_FOLLOW( - const unsigned opt = 0; - if (argc != 2) bb_show_usage(); - fname = argv[1]; - ) + opt = getopt32(argv, "^" "n" IF_FEATURE_READLINK_FOLLOW("fvsq") + "\0" "=1"); + fname = argv[optind]; /* compat: coreutils readlink reports errors silently via exit code */ if (!(opt & 4)) /* not -v */ logmode = LOGMODE_NONE; /* NOFORK: only one alloc is allowed; must free */ - if (opt & 1) { /* -f */ + if (opt & 2) { /* -f */ buf = xmalloc_realpath_coreutils(fname); } else { buf = xmalloc_readlink_or_warn(fname); @@ -93,7 +88,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) if (!buf) return EXIT_FAILURE; - printf((opt & 2) ? "%s" : "%s\n", buf); + printf((opt & 1) ? "%s" : "%s\n", buf); free(buf); fflush_stdout_and_exit_SUCCESS(); -- cgit v1.2.3-55-g6feb