aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-01-05 11:17:37 +0000
committerRon Yorston <rmy@pobox.com>2024-01-05 11:17:37 +0000
commit49edb26faaddb81e6333e7891715ce13301aed09 (patch)
tree8f982e294e2d0ac916f28ad8ef9344611cd93f25
parentf72312908b11605f527d002b4e8ce729bbe237a5 (diff)
parent5dc9ece3b9e87af0dcb01449821ac827391ac116 (diff)
downloadbusybox-w32-49edb26faaddb81e6333e7891715ce13301aed09.tar.gz
busybox-w32-49edb26faaddb81e6333e7891715ce13301aed09.tar.bz2
busybox-w32-49edb26faaddb81e6333e7891715ce13301aed09.zip
Merge branch 'busybox' into merge
-rw-r--r--editors/awk.c33
-rw-r--r--editors/sed.c5
-rw-r--r--miscutils/time.c73
-rwxr-xr-xtestsuite/awk.tests7
-rwxr-xr-xtestsuite/time.tests37
-rw-r--r--util-linux/lsusb.c28
6 files changed, 135 insertions, 48 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 7fb629273..3ca0c5fce 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -555,8 +555,9 @@ struct globals {
555 //we are reusing ahash as fdhash, via define (see later) 555 //we are reusing ahash as fdhash, via define (see later)
556 const char *g_progname; 556 const char *g_progname;
557 int g_lineno; 557 int g_lineno;
558 int nfields; 558 int num_fields; /* number of existing $N's */
559 unsigned maxfields; 559 unsigned num_alloc_fields; /* current size of Fields[] */
560 /* NB: Fields[0] corresponds to $1, not to $0 */
560 var *Fields; 561 var *Fields;
561 char *g_pos; 562 char *g_pos;
562 char g_saved_ch; 563 char g_saved_ch;
@@ -631,8 +632,8 @@ struct globals2 {
631// for fdhash in execution stage. 632// for fdhash in execution stage.
632#define g_progname (G1.g_progname ) 633#define g_progname (G1.g_progname )
633#define g_lineno (G1.g_lineno ) 634#define g_lineno (G1.g_lineno )
634#define nfields (G1.nfields ) 635#define num_fields (G1.num_fields )
635#define maxfields (G1.maxfields ) 636#define num_alloc_fields (G1.num_alloc_fields)
636#define Fields (G1.Fields ) 637#define Fields (G1.Fields )
637#define g_pos (G1.g_pos ) 638#define g_pos (G1.g_pos )
638#define g_saved_ch (G1.g_saved_ch ) 639#define g_saved_ch (G1.g_saved_ch )
@@ -1966,30 +1967,30 @@ static void fsrealloc(int size)
1966{ 1967{
1967 int i, newsize; 1968 int i, newsize;
1968 1969
1969 if ((unsigned)size >= maxfields) { 1970 if ((unsigned)size >= num_alloc_fields) {
1970 /* Sanity cap, easier than catering for over/underflows */ 1971 /* Sanity cap, easier than catering for over/underflows */
1971 if ((unsigned)size > 0xffffff) 1972 if ((unsigned)size > 0xffffff)
1972 bb_die_memory_exhausted(); 1973 bb_die_memory_exhausted();
1973 1974
1974 i = maxfields; 1975 i = num_alloc_fields;
1975 maxfields = size + 16; 1976 num_alloc_fields = size + 16;
1976 1977
1977 newsize = maxfields * sizeof(Fields[0]); 1978 newsize = num_alloc_fields * sizeof(Fields[0]);
1978 debug_printf_eval("fsrealloc: xrealloc(%p, %u)\n", Fields, newsize); 1979 debug_printf_eval("fsrealloc: xrealloc(%p, %u)\n", Fields, newsize);
1979 Fields = xrealloc(Fields, newsize); 1980 Fields = xrealloc(Fields, newsize);
1980 debug_printf_eval("fsrealloc: Fields=%p..%p\n", Fields, (char*)Fields + newsize - 1); 1981 debug_printf_eval("fsrealloc: Fields=%p..%p\n", Fields, (char*)Fields + newsize - 1);
1981 /* ^^^ did Fields[] move? debug aid for L.v getting "upstaged" by R.v in evaluate() */ 1982 /* ^^^ did Fields[] move? debug aid for L.v getting "upstaged" by R.v in evaluate() */
1982 1983
1983 for (; i < maxfields; i++) { 1984 for (; i < num_alloc_fields; i++) {
1984 Fields[i].type = VF_SPECIAL; 1985 Fields[i].type = VF_SPECIAL | VF_DIRTY;
1985 Fields[i].string = NULL; 1986 Fields[i].string = NULL;
1986 } 1987 }
1987 } 1988 }
1988 /* if size < nfields, clear extra field variables */ 1989 /* if size < num_fields, clear extra field variables */
1989 for (i = size; i < nfields; i++) { 1990 for (i = size; i < num_fields; i++) {
1990 clrvar(Fields + i); 1991 clrvar(Fields + i);
1991 } 1992 }
1992 nfields = size; 1993 num_fields = size;
1993} 1994}
1994 1995
1995static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[]) 1996static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[])
@@ -2126,7 +2127,7 @@ static void split_f0(void)
2126 /* set NF manually to avoid side effects */ 2127 /* set NF manually to avoid side effects */
2127 clrvar(intvar[NF]); 2128 clrvar(intvar[NF]);
2128 intvar[NF]->type = VF_NUMBER | VF_SPECIAL; 2129 intvar[NF]->type = VF_NUMBER | VF_SPECIAL;
2129 intvar[NF]->number = nfields; 2130 intvar[NF]->number = num_fields;
2130#undef fstrings 2131#undef fstrings
2131} 2132}
2132 2133
@@ -2999,7 +3000,7 @@ static var *evaluate(node *op, var *res)
2999 syntax_error(EMSG_TOO_FEW_ARGS); 3000 syntax_error(EMSG_TOO_FEW_ARGS);
3000 L.v = evaluate(op1, TMPVAR0); 3001 L.v = evaluate(op1, TMPVAR0);
3001 /* Does L.v point to $n variable? */ 3002 /* Does L.v point to $n variable? */
3002 if ((size_t)(L.v - Fields) < maxfields) { 3003 if ((size_t)(L.v - Fields) < num_alloc_fields) {
3003 /* yes, remember where Fields[] is */ 3004 /* yes, remember where Fields[] is */
3004 old_Fields_ptr = Fields; 3005 old_Fields_ptr = Fields;
3005 } 3006 }
@@ -3553,7 +3554,7 @@ static var *evaluate(node *op, var *res)
3553 res = intvar[F0]; 3554 res = intvar[F0];
3554 } else { 3555 } else {
3555 split_f0(); 3556 split_f0();
3556 if (i > nfields) 3557 if (i > num_fields)
3557 fsrealloc(i); 3558 fsrealloc(i);
3558 res = &Fields[i - 1]; 3559 res = &Fields[i - 1];
3559 } 3560 }
diff --git a/editors/sed.c b/editors/sed.c
index 07f7b7a9b..107e664a0 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1669,6 +1669,11 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1669 fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); 1669 fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);
1670 1670
1671 process_files(); 1671 process_files();
1672 fflush(G.nonstdout);
1673 if (ferror(G.nonstdout)) {
1674 xfunc_error_retval = 4; /* It's what gnu sed exits with... */
1675 bb_simple_error_msg_and_die(bb_msg_write_error);
1676 }
1672 fclose(G.nonstdout); 1677 fclose(G.nonstdout);
1673 G.nonstdout = stdout; 1678 G.nonstdout = stdout;
1674 1679
diff --git a/miscutils/time.c b/miscutils/time.c
index 2c71382bf..1048afa7d 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -127,6 +127,7 @@ static void printargv(char *const *argv)
127 } while (*++argv); 127 } while (*++argv);
128} 128}
129 129
130#ifdef UNUSED
130/* Return the number of kilobytes corresponding to a number of pages PAGES. 131/* Return the number of kilobytes corresponding to a number of pages PAGES.
131 (Actually, we use it to convert pages*ticks into kilobytes*ticks.) 132 (Actually, we use it to convert pages*ticks into kilobytes*ticks.)
132 133
@@ -152,7 +153,8 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages)
152 return tmp / 1024; /* then smaller. */ 153 return tmp / 1024; /* then smaller. */
153} 154}
154#undef pagesize 155#undef pagesize
155#endif 156#endif /* UNUSED */
157#endif /* !ENABLE_PLATFORM_MINGW32 */
156 158
157/* summarize: Report on the system use of a command. 159/* summarize: Report on the system use of a command.
158 160
@@ -249,36 +251,31 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
249 } 251 }
250 252
251 switch (*fmt) { 253 switch (*fmt) {
252#ifdef NOT_NEEDED
253 /* Handle literal char */
254 /* Usually we optimize for size, but there is a limit
255 * for everything. With this we do a lot of 1-byte writes */
256 default:
257 bb_putchar(*fmt);
258 break;
259#endif
260
261 case '%': 254 case '%':
262 switch (*++fmt) { 255 switch (*++fmt) {
263#ifdef NOT_NEEDED_YET 256#if !ENABLE_PLATFORM_MINGW32
264 /* Our format strings do not have these */
265 /* and we do not take format str from user */
266 default: 257 default:
267 bb_putchar('%'); 258 /* Unknown %<char> is printed as "?<char>" */
259 bb_putchar('?');
260 if (!*fmt) {
261 /* Trailing -f '...%' prints "...?" but NOT newline */
262 goto ret;
263 }
268 /*FALLTHROUGH*/ 264 /*FALLTHROUGH*/
269 case '%': 265 case '%':
270 if (!*fmt) goto ret;
271 bb_putchar(*fmt); 266 bb_putchar(*fmt);
272 break; 267 break;
273#endif
274#if !ENABLE_PLATFORM_MINGW32
275 case 'C': /* The command that got timed. */ 268 case 'C': /* The command that got timed. */
276 printargv(command); 269 printargv(command);
277 break; 270 break;
278 case 'D': /* Average unshared data size. */ 271 case 'D': /* Average unshared data size. */
272 /* (linux kernel sets ru_idrss/isrss/ixrss to 0,
273 * docs say the value is in kbytes, so ptok() is wrong) */
279 printf("%lu", 274 printf("%lu",
280 (ptok(pagesize, (UL) resp->ru.ru_idrss) + 275 (/*ptok(pagesize,*/ (UL) resp->ru.ru_idrss +
281 ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); 276 (UL) resp->ru.ru_isrss
277 ) / cpu_ticks
278 );
282 break; 279 break;
283#endif 280#endif
284 case 'E': { /* Elapsed real (wall clock) time. */ 281 case 'E': { /* Elapsed real (wall clock) time. */
@@ -303,13 +300,17 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
303 printf("%lu", resp->ru.ru_inblock); 300 printf("%lu", resp->ru.ru_inblock);
304 break; 301 break;
305 case 'K': /* Average mem usage == data+stack+text. */ 302 case 'K': /* Average mem usage == data+stack+text. */
303 /* (linux kernel sets ru_idrss/isrss/ixrss to 0,
304 * docs say the value is in kbytes, so ptok() is wrong) */
306 printf("%lu", 305 printf("%lu",
307 (ptok(pagesize, (UL) resp->ru.ru_idrss) + 306 (/*ptok(pagesize,*/ (UL) resp->ru.ru_idrss +
308 ptok(pagesize, (UL) resp->ru.ru_isrss) + 307 (UL) resp->ru.ru_isrss +
309 ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks); 308 (UL) resp->ru.ru_ixrss
309 ) / cpu_ticks
310 );
310 break; 311 break;
311 case 'M': /* Maximum resident set size. */ 312 case 'M': /* Maximum resident set size. */
312 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss)); 313 printf("%lu", (UL) resp->ru.ru_maxrss);
313 break; 314 break;
314 case 'O': /* Outputs. */ 315 case 'O': /* Outputs. */
315 printf("%lu", resp->ru.ru_oublock); 316 printf("%lu", resp->ru.ru_oublock);
@@ -364,7 +365,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
364 printf("%lu", resp->ru.ru_nswap); 365 printf("%lu", resp->ru.ru_nswap);
365 break; 366 break;
366 case 'X': /* Average shared text size. */ 367 case 'X': /* Average shared text size. */
367 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks); 368 printf("%lu", /*ptok(pagesize,*/ (UL) resp->ru.ru_ixrss / cpu_ticks);
368 break; 369 break;
369 case 'Z': /* Page size. */ 370 case 'Z': /* Page size. */
370 printf("%u", pagesize); 371 printf("%u", pagesize);
@@ -383,7 +384,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
383 printf("%lu", resp->ru.ru_nsignals); 384 printf("%lu", resp->ru.ru_nsignals);
384 break; 385 break;
385 case 'p': /* Average stack segment. */ 386 case 'p': /* Average stack segment. */
386 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks); 387 printf("%lu", /*ptok(pagesize,*/ (UL) resp->ru.ru_isrss / cpu_ticks);
387 break; 388 break;
388 case 'r': /* Incoming socket messages received. */ 389 case 'r': /* Incoming socket messages received. */
389 printf("%lu", resp->ru.ru_msgrcv); 390 printf("%lu", resp->ru.ru_msgrcv);
@@ -392,7 +393,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
392 printf("%lu", resp->ru.ru_msgsnd); 393 printf("%lu", resp->ru.ru_msgsnd);
393 break; 394 break;
394 case 't': /* Average resident set size. */ 395 case 't': /* Average resident set size. */
395 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks); 396 printf("%lu", /*ptok(pagesize,*/ (UL) resp->ru.ru_idrss / cpu_ticks);
396 break; 397 break;
397 case 'w': /* Voluntary context switches. */ 398 case 'w': /* Voluntary context switches. */
398 printf("%lu", resp->ru.ru_nvcsw); 399 printf("%lu", resp->ru.ru_nvcsw);
@@ -404,14 +405,22 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
404 } 405 }
405 break; 406 break;
406 407
407#ifdef NOT_NEEDED_YET 408#if !ENABLE_PLATFORM_MINGW32
408 case '\\': /* Format escape. */ 409 default: /* *fmt is '\': format escape */
409 switch (*++fmt) { 410 switch (*++fmt) {
410 default: 411 default:
412 /* Unknown \<char> is printed as "?\<char>" */
413 bb_putchar('?');
411 bb_putchar('\\'); 414 bb_putchar('\\');
415 if (!*fmt) {
416 /* Trailing -f '...\': GNU time 1.9 prints
417 * "...?\COMMAND" (it's probably a bug).
418 */
419 puts(command[0]);
420 goto ret;
421 }
412 /*FALLTHROUGH*/ 422 /*FALLTHROUGH*/
413 case '\\': 423 case '\\':
414 if (!*fmt) goto ret;
415 bb_putchar(*fmt); 424 bb_putchar(*fmt);
416 break; 425 break;
417 case 't': 426 case 't':
@@ -426,8 +435,10 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
426 } 435 }
427 ++fmt; 436 ++fmt;
428 } 437 }
429 /* ret: */
430 bb_putchar('\n'); 438 bb_putchar('\n');
439#if !ENABLE_PLATFORM_MINGW32
440 ret: ;
441#endif
431} 442}
432 443
433/* Run command CMD and return statistics on it. 444/* Run command CMD and return statistics on it.
@@ -469,7 +480,7 @@ int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
469int time_main(int argc UNUSED_PARAM, char **argv) 480int time_main(int argc UNUSED_PARAM, char **argv)
470{ 481{
471 resource_t res; 482 resource_t res;
472 /* $TIME has lowest prio (-v,-p,-f FMT overrride it) */ 483 /* $TIME has lowest prio (-v,-p,-f FMT override it) */
473 const char *output_format = getenv("TIME") ? : default_format; 484 const char *output_format = getenv("TIME") ? : default_format;
474 char *output_filename; 485 char *output_filename;
475 int output_fd; 486 int output_fd;
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index 0a84dc13e..afbde01c0 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -606,6 +606,13 @@ testing 'awk gensub backslashes \\0' \
606\\0|\\0 606\\0|\\0
607' '' '' 607' '' ''
608 608
609# References to empty (not provided in the input) fields in first versus subsequent lines
610testing 'awk references to empty fields' \
611 'awk '$sq'$2 != 0'$sq \
612 'a
613b
614' '' 'a\nb\n'
615
609# The "b" in "abc" should not match <b* pattern. 616# The "b" in "abc" should not match <b* pattern.
610# Currently we use REG_STARTEND ("This flag is a BSD extension, not present in POSIX") 617# Currently we use REG_STARTEND ("This flag is a BSD extension, not present in POSIX")
611# to implement the code to handle this correctly, but if your libc has no REG_STARTEND, 618# to implement the code to handle this correctly, but if your libc has no REG_STARTEND,
diff --git a/testsuite/time.tests b/testsuite/time.tests
new file mode 100755
index 000000000..4e31b3868
--- /dev/null
+++ b/testsuite/time.tests
@@ -0,0 +1,37 @@
1#!/bin/sh
2
3# Copyright 2024 by Denys Vlasenko <vda.linux@googlemail.com>
4# Licensed under GPLv2, see file LICENSE in this source tree.
5
6. ./testing.sh
7
8# testing "description" "arguments" "result" "infile" "stdin"
9
10testing "time -f trailing backslash" \
11 "time -f 'abc\' sleep 0 2>&1" \
12 'abc?\sleep\n' '' ''
13# ^^^^^^^^^^^^^^ this is what GNU time version 1.9 prints
14
15testing "time -f trailing percent" \
16 "time -f 'abc%' sleep 0 2>&1" \
17 'abc?' '' ''
18
19testing "time -f undefined backslash" \
20 "time -f 'abc\^def' sleep 0 2>&1" \
21 'abc?\^def\n' '' ''
22
23testing "time -f undefined percent" \
24 "time -f 'abc%^def' sleep 0 2>&1" \
25 'abc?^def\n' '' ''
26
27testing "time -f backslash tab and newline" \
28 "time -f 'abc\ndef\txyz' sleep 0 2>&1" \
29 'abc
30def xyz
31' '' ''
32
33testing "time -f percent percent" \
34 "time -f 'abc%%def' sleep 0 2>&1" \
35 'abc%def\n' '' ''
36
37exit $FAILCOUNT
diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c
index 262c70a1b..0a9e505f4 100644
--- a/util-linux/lsusb.c
+++ b/util-linux/lsusb.c
@@ -24,6 +24,24 @@
24 24
25#include "libbb.h" 25#include "libbb.h"
26 26
27static char * FAST_FUNC add_sysfs_prop(const char *dir, const char *suffix,
28 char *buf, size_t size)
29{
30 char *filename;
31 ssize_t len;
32
33 filename = concat_path_file(dir, suffix);
34 len = open_read_close(filename, buf, size - 1);
35 free(filename);
36
37 if (len < 0)
38 len = 0;
39
40 buf[len] = '\0';
41
42 return trim(buf);
43}
44
27static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM, 45static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
28 const char *fileName, 46 const char *fileName,
29 struct stat *statbuf UNUSED_PARAM) 47 struct stat *statbuf UNUSED_PARAM)
@@ -61,7 +79,15 @@ static int FAST_FUNC fileAction(struct recursive_state *state UNUSED_PARAM,
61 config_close(parser); 79 config_close(parser);
62 80
63 if (busnum) { 81 if (busnum) {
64 printf("Bus %s Device %s: ID %04x:%04x\n", busnum, devnum, product_vid, product_did); 82 char name[256], *p;
83
84 p = add_sysfs_prop(fileName, "/manufacturer", name, sizeof(name) - 1);
85 if (p != name)
86 p = stpcpy(p, " ");
87 add_sysfs_prop(fileName, "/product", p, name + sizeof(name) - p);
88
89 printf("Bus %s Device %s: ID %04x:%04x %s\n", busnum, devnum,
90 product_vid, product_did, name);
65 free(busnum); 91 free(busnum);
66 free(devnum); 92 free(devnum);
67 } 93 }