Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/findutils/xargs.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/findutils/xargs.c
r3232 r3621 54 54 //config: instead of whitespace, and the quotes and backslash 55 55 //config: are not special. 56 //config: 57 //config:config FEATURE_XARGS_SUPPORT_REPL_STR 58 //config: bool "Enable -I STR: string to replace" 59 //config: default y 60 //config: depends on XARGS 61 //config: help 62 //config: Support -I STR and -i[STR] options. 56 63 57 64 //applet:IF_XARGS(APPLET_NOEXEC(xargs, xargs, BB_DIR_USR_BIN, BB_SUID_DROP, xargs)) … … 60 67 61 68 #include "libbb.h" 69 #include "common_bufsiz.h" 62 70 63 71 /* This is a NOEXEC applet. Be very careful! */ … … 86 94 struct globals { 87 95 char **args; 96 #if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 97 char **argv; 98 const char *repl_str; 99 char eol_ch; 100 #endif 88 101 const char *eof_str; 89 102 int idx; 90 103 } FIX_ALIASING; 91 #define G (*(struct globals*) &bb_common_bufsiz1)104 #define G (*(struct globals*)bb_common_bufsiz1) 92 105 #define INIT_G() do { \ 106 setup_common_bufsiz(); \ 93 107 G.eof_str = NULL; /* need to clear by hand because we are NOEXEC applet */ \ 108 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.repl_str = "{}";) \ 109 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\n';) \ 94 110 } while (0) 95 111 96 112 97 /*98 * This function has special algorithm.99 * Don't use fork and include to main!100 */101 113 static int xargs_exec(void) 102 114 { … … 113 125 } 114 126 if (status >= 0x180) { 115 bb_error_msg(" %s:terminated by signal %d",127 bb_error_msg("'%s' terminated by signal %d", 116 128 G.args[0], status - 0x180); 117 129 return 125; … … 142 154 * If reading discovers that last chars do not form the complete 143 155 * parameter, the pointer to the first such "tail character" is returned. 144 * (buf has extra byte at the end to accom odate terminating NUL156 * (buf has extra byte at the end to accommodate terminating NUL 145 157 * of "tail characters" string). 146 158 * Otherwise, the returned pointer points to NUL byte. … … 302 314 } 303 315 *p++ = c; 304 if (c == '\0') { /* word's delimiteror EOF detected */316 if (c == '\0') { /* NUL or EOF detected */ 305 317 /* A full word is loaded */ 306 318 store_param(s); … … 324 336 #endif /* FEATURE_XARGS_SUPPORT_ZERO_TERM */ 325 337 338 #if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 339 /* 340 * Used if -I<repl> was specified. 341 * In this mode, words aren't appended to PROG ARGS. 342 * Instead, entire input line is read, then <repl> string 343 * in every PROG and ARG is replaced with the line: 344 * echo -e "ho ho\nhi" | xargs -I_ cmd __ _ 345 * results in "cmd 'ho hoho ho' 'ho ho'"; "cmd 'hihi' 'hi'". 346 * -n MAX_ARGS seems to be ignored. 347 * Tested with GNU findutils 4.5.10. 348 */ 349 //FIXME: n_max_chars is not handled the same way as in GNU findutils. 350 //FIXME: quoting is not implemented. 351 static char* FAST_FUNC process_stdin_with_replace(int n_max_chars, int n_max_arg UNUSED_PARAM, char *buf) 352 { 353 int i; 354 char *end, *p; 355 356 /* Free strings from last invocation, if any */ 357 for (i = 0; G.args && G.args[i]; i++) 358 if (G.args[i] != G.argv[i]) 359 free(G.args[i]); 360 361 end = buf + n_max_chars; 362 p = buf; 363 364 while (1) { 365 int c = getchar(); 366 if (c == EOF || c == G.eol_ch) { 367 if (p == buf) 368 goto ret; /* empty line */ 369 c = '\0'; 370 } 371 *p++ = c; 372 if (c == '\0') { /* EOL or EOF detected */ 373 i = 0; 374 while (G.argv[i]) { 375 char *arg = G.argv[i]; 376 int count = count_strstr(arg, G.repl_str); 377 if (count != 0) 378 arg = xmalloc_substitute_string(arg, count, G.repl_str, buf); 379 store_param(arg); 380 dbg_msg("args[]:'%s'", arg); 381 i++; 382 } 383 p = buf; 384 goto ret; 385 } 386 if (p == end) { 387 goto ret; 388 } 389 } 390 ret: 391 *p = '\0'; 392 /* store_param(NULL) - caller will do it */ 393 dbg_msg("return:'%s'", buf); 394 return buf; 395 } 396 #endif 397 326 398 #if ENABLE_FEATURE_XARGS_SUPPORT_CONFIRMATION 327 399 /* Prompt the user for a response, and 328 if the user responds affirmatively, return true; 329 otherwise, return false. Uses "/dev/tty", not stdin. */ 400 * if user responds affirmatively, return true; 401 * otherwise, return false. Uses "/dev/tty", not stdin. 402 */ 330 403 static int xargs_ask_confirmation(void) 331 404 { … … 361 434 //usage: "\n -n N Pass no more than N args to PROG" 362 435 //usage: "\n -s N Pass command line of no more than N bytes" 436 //usage: IF_FEATURE_XARGS_SUPPORT_REPL_STR( 437 //usage: "\n -I STR Replace STR within PROG ARGS with input line" 438 //usage: ) 363 439 //usage: IF_FEATURE_XARGS_SUPPORT_TERMOPT( 364 440 //usage: "\n -x Exit if size is exceeded" … … 379 455 IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) 380 456 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) 457 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,) 458 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,) 381 459 382 460 OPT_VERBOSE = 1 << OPTBIT_VERBOSE , … … 389 467 OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0, 390 468 OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0, 469 OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0, 470 OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0, 391 471 }; 392 472 #define OPTION_STR "+trn:s:e::E:" \ 393 473 IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ 394 474 IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ 395 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") 475 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \ 476 IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::") 396 477 397 478 int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; … … 406 487 int n_max_chars; 407 488 int n_max_arg; 408 #if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM 489 #if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \ 490 || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 409 491 char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin; 410 492 #else … … 420 502 ; 421 503 #endif 422 opt = getopt32(argv, OPTION_STR, &max_args, &max_chars, &G.eof_str, &G.eof_str); 504 opt = getopt32(argv, OPTION_STR, 505 &max_args, &max_chars, &G.eof_str, &G.eof_str 506 IF_FEATURE_XARGS_SUPPORT_REPL_STR(, &G.repl_str, &G.repl_str) 507 ); 423 508 424 509 /* -E ""? You may wonder why not just omit -E? … … 428 513 G.eof_str = NULL; 429 514 430 if (opt & OPT_ZEROTERM) 431 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin); 515 if (opt & OPT_ZEROTERM) { 516 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin;) 517 IF_FEATURE_XARGS_SUPPORT_REPL_STR(G.eol_ch = '\0';) 518 } 432 519 433 520 argv += optind; … … 439 526 } 440 527 441 /* -s NUM default. fileutils-4.4.2 uses 128k, but I heasitate 442 * to use such a big value - first need to change code to use 443 * growable buffer instead of fixed one. 444 */ 445 n_max_chars = 32 * 1024; 446 /* Make smaller if system does not allow our default value. 528 /* 447 529 * The Open Group Base Specifications Issue 6: 448 530 * "The xargs utility shall limit the command line length such that … … 452 534 * shall not exceed {ARG_MAX}-2048 bytes". 453 535 */ 454 { 455 long arg_max = 0; 456 #if defined _SC_ARG_MAX 457 arg_max = sysconf(_SC_ARG_MAX) - 2048; 458 #elif defined ARG_MAX 459 arg_max = ARG_MAX - 2048; 460 #endif 461 if (arg_max > 0 && n_max_chars > arg_max) 462 n_max_chars = arg_max; 463 } 536 n_max_chars = bb_arg_max(); 537 if (n_max_chars > 32 * 1024) 538 n_max_chars = 32 * 1024; 539 /* 540 * POSIX suggests substracting 2048 bytes from sysconf(_SC_ARG_MAX) 541 * so that the process may safely modify its environment. 542 */ 543 n_max_chars -= 2048; 544 464 545 if (opt & OPT_UPTO_SIZE) { 465 546 n_max_chars = xatou_range(max_chars, 1, INT_MAX); … … 487 568 } 488 569 489 /* Allocate pointers for execvp */ 490 /* We can statically allocate (argc + n_max_arg + 1) elements 491 * and do not bother with resizing args[], but on 64-bit machines 492 * this results in args[] vector which is ~8 times bigger 493 * than n_max_chars! That is, with n_max_chars == 20k, 494 * args[] will take 160k (!), which will most likely be 495 * almost entirely unused. 496 */ 497 /* See store_param() for matching 256-step growth logic */ 498 G.args = xmalloc(sizeof(G.args[0]) * ((argc + 0xff) & ~0xff)); 499 500 /* Store the command to be executed, part 1 */ 501 for (i = 0; argv[i]; i++) 502 G.args[i] = argv[i]; 570 #if ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 571 if (opt & (OPT_REPLSTR | OPT_REPLSTR1)) { 572 /* 573 * -I<str>: 574 * Unmodified args are kept in G.argv[i], 575 * G.args[i] receives malloced G.argv[i] with <str> replaced 576 * with input line. Setting this up: 577 */ 578 G.args = NULL; 579 G.argv = argv; 580 argc = 0; 581 read_args = process_stdin_with_replace; 582 /* Make -I imply -r. GNU findutils seems to do the same: */ 583 /* (otherwise "echo -n | xargs -I% echo %" would SEGV) */ 584 opt |= OPT_NO_EMPTY; 585 } else 586 #endif 587 { 588 /* Allocate pointers for execvp. 589 * We can statically allocate (argc + n_max_arg + 1) elements 590 * and do not bother with resizing args[], but on 64-bit machines 591 * this results in args[] vector which is ~8 times bigger 592 * than n_max_chars! That is, with n_max_chars == 20k, 593 * args[] will take 160k (!), which will most likely be 594 * almost entirely unused. 595 * 596 * See store_param() for matching 256-step growth logic 597 */ 598 G.args = xmalloc(sizeof(G.args[0]) * ((argc + 0xff) & ~0xff)); 599 /* Store the command to be executed, part 1 */ 600 for (i = 0; argv[i]; i++) 601 G.args[i] = argv[i]; 602 } 503 603 504 604 while (1) {
Note:
See TracChangeset
for help on using the changeset viewer.