diff options
| author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-09-29 08:20:30 +0000 |
|---|---|---|
| committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-09-29 08:20:30 +0000 |
| commit | f005e8def05cd37e733547f512851ebbef357d1e (patch) | |
| tree | 89e5415774982c6293dc40f684543732d2378abb | |
| parent | 0a8154ed4662458156096f88756e22284b149396 (diff) | |
| download | busybox-w32-f005e8def05cd37e733547f512851ebbef357d1e.tar.gz busybox-w32-f005e8def05cd37e733547f512851ebbef357d1e.tar.bz2 busybox-w32-f005e8def05cd37e733547f512851ebbef357d1e.zip | |
xargs: simplify option parsing
git-svn-id: svn://busybox.net/trunk/busybox@16256 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -rw-r--r-- | findutils/xargs.c | 207 | ||||
| -rw-r--r-- | libbb/getopt_ulflags.c | 1 |
2 files changed, 92 insertions, 116 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c index d067a3f48..b6a154f15 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
| @@ -45,54 +45,52 @@ | |||
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | /* | 47 | /* |
| 48 | This function have special algorithm. | 48 | This function has special algorithm. |
| 49 | Don`t use fork and include to main! | 49 | Don't use fork and include to main! |
| 50 | */ | 50 | */ |
| 51 | static int xargs_exec(char *const *args) | 51 | static int xargs_exec(char *const *args) |
| 52 | { | 52 | { |
| 53 | pid_t p; | 53 | pid_t p; |
| 54 | volatile int exec_errno = 0; /* shared vfork stack */ | 54 | volatile int exec_errno = 0; /* shared vfork stack */ |
| 55 | int status; | ||
| 55 | 56 | ||
| 56 | if ((p = vfork()) >= 0) { | 57 | p = vfork(); |
| 57 | if (p == 0) { | 58 | if (p < 0) |
| 58 | /* vfork -- child */ | ||
| 59 | execvp(args[0], args); | ||
| 60 | exec_errno = errno; /* set error to shared stack */ | ||
| 61 | _exit(1); | ||
| 62 | } else { | ||
| 63 | /* vfork -- parent */ | ||
| 64 | int status; | ||
| 65 | |||
| 66 | while (wait(&status) == (pid_t) - 1) | ||
| 67 | if (errno != EINTR) | ||
| 68 | break; | ||
| 69 | if (exec_errno) { | ||
| 70 | errno = exec_errno; | ||
| 71 | bb_perror_msg("%s", args[0]); | ||
| 72 | return exec_errno == ENOENT ? 127 : 126; | ||
| 73 | } else { | ||
| 74 | if (WEXITSTATUS(status) == 255) { | ||
| 75 | bb_error_msg("%s: exited with status 255; aborting", args[0]); | ||
| 76 | return 124; | ||
| 77 | } | ||
| 78 | if (WIFSTOPPED(status)) { | ||
| 79 | bb_error_msg("%s: stopped by signal %d", | ||
| 80 | args[0], WSTOPSIG(status)); | ||
| 81 | return 125; | ||
| 82 | } | ||
| 83 | if (WIFSIGNALED(status)) { | ||
| 84 | bb_error_msg("%s: terminated by signal %d", | ||
| 85 | args[0], WTERMSIG(status)); | ||
| 86 | return 125; | ||
| 87 | } | ||
| 88 | if (WEXITSTATUS(status) != 0) | ||
| 89 | return 123; | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } else { | ||
| 94 | bb_perror_msg_and_die("vfork"); | 59 | bb_perror_msg_and_die("vfork"); |
| 60 | |||
| 61 | if (p == 0) { | ||
| 62 | /* vfork -- child */ | ||
| 63 | execvp(args[0], args); | ||
| 64 | exec_errno = errno; /* set error to shared stack */ | ||
| 65 | _exit(1); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* vfork -- parent */ | ||
| 69 | while (wait(&status) == (pid_t) -1) | ||
| 70 | if (errno != EINTR) | ||
| 71 | break; | ||
| 72 | if (exec_errno) { | ||
| 73 | errno = exec_errno; | ||
| 74 | bb_perror_msg("%s", args[0]); | ||
| 75 | return exec_errno == ENOENT ? 127 : 126; | ||
| 95 | } | 76 | } |
| 77 | if (WEXITSTATUS(status) == 255) { | ||
| 78 | bb_error_msg("%s: exited with status 255; aborting", args[0]); | ||
| 79 | return 124; | ||
| 80 | } | ||
| 81 | if (WIFSTOPPED(status)) { | ||
| 82 | bb_error_msg("%s: stopped by signal %d", | ||
| 83 | args[0], WSTOPSIG(status)); | ||
| 84 | return 125; | ||
| 85 | } | ||
| 86 | if (WIFSIGNALED(status)) { | ||
| 87 | bb_error_msg("%s: terminated by signal %d", | ||
| 88 | args[0], WTERMSIG(status)); | ||
| 89 | return 125; | ||
| 90 | } | ||
| 91 | if (WEXITSTATUS(status)) | ||
| 92 | return 123; | ||
| 93 | return 0; | ||
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | 96 | ||
| @@ -105,7 +103,7 @@ typedef struct xlist_s { | |||
| 105 | static int eof_stdin_detected; | 103 | static int eof_stdin_detected; |
| 106 | 104 | ||
| 107 | #define ISBLANK(c) ((c) == ' ' || (c) == '\t') | 105 | #define ISBLANK(c) ((c) == ' ' || (c) == '\t') |
| 108 | #define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \ | 106 | #define ISSPACE(c) (ISBLANK(c) || (c) == '\n' || (c) == '\r' \ |
| 109 | || (c) == '\f' || (c) == '\v') | 107 | || (c) == '\f' || (c) == '\v') |
| 110 | 108 | ||
| 111 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES | 109 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES |
| @@ -304,19 +302,10 @@ static int xargs_ask_confirmation(void) | |||
| 304 | return 1; | 302 | return 1; |
| 305 | return 0; | 303 | return 0; |
| 306 | } | 304 | } |
| 307 | |||
| 308 | # define OPT_INC_P 1 | ||
| 309 | #else | 305 | #else |
| 310 | # define OPT_INC_P 0 | ||
| 311 | # define xargs_ask_confirmation() 1 | 306 | # define xargs_ask_confirmation() 1 |
| 312 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION */ | 307 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION */ |
| 313 | 308 | ||
| 314 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT | ||
| 315 | # define OPT_INC_X 1 | ||
| 316 | #else | ||
| 317 | # define OPT_INC_X 0 | ||
| 318 | #endif | ||
| 319 | |||
| 320 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM | 309 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM |
| 321 | static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE_UNUSED, | 310 | static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE_UNUSED, |
| 322 | size_t mc, char *buf) | 311 | size_t mc, char *buf) |
| @@ -371,35 +360,37 @@ static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE | |||
| 371 | } | 360 | } |
| 372 | return list_arg; | 361 | return list_arg; |
| 373 | } | 362 | } |
| 374 | |||
| 375 | # define READ_ARGS(l, e, nmc, mc) (*read_args)(l, e, nmc, mc) | ||
| 376 | # define OPT_INC_0 1 /* future use */ | ||
| 377 | #else | ||
| 378 | # define OPT_INC_0 0 /* future use */ | ||
| 379 | # define READ_ARGS(l, e, nmc, mc) process_stdin(l, e, nmc, mc) | ||
| 380 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM */ | 363 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM */ |
| 381 | 364 | ||
| 382 | 365 | /* Correct regardless of combination of CONFIG_xxx */ | |
| 383 | #define OPT_VERBOSE (1<<0) | 366 | enum { |
| 384 | #define OPT_NO_EMPTY (1<<1) | 367 | OPTBIT_VERBOSE = 0, |
| 385 | #define OPT_UPTO_NUMBER (1<<2) | 368 | OPTBIT_NO_EMPTY, |
| 386 | #define OPT_UPTO_SIZE (1<<3) | 369 | OPTBIT_UPTO_NUMBER, |
| 387 | #define OPT_EOF_STRING (1<<4) | 370 | OPTBIT_UPTO_SIZE, |
| 388 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION | 371 | OPTBIT_EOF_STRING, |
| 389 | #define OPT_INTERACTIVE (1<<5) | 372 | USE_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) |
| 390 | #else | 373 | USE_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) |
| 391 | #define OPT_INTERACTIVE (0) /* require for algorithm &| */ | 374 | USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) |
| 392 | #endif | 375 | |
| 393 | #define OPT_TERMINATE (1<<(5+OPT_INC_P)) | 376 | OPT_VERBOSE = 1<<OPTBIT_VERBOSE , |
| 394 | #define OPT_ZEROTERM (1<<(5+OPT_INC_P+OPT_INC_X)) | 377 | OPT_NO_EMPTY = 1<<OPTBIT_NO_EMPTY , |
| 395 | /* next future | 378 | OPT_UPTO_NUMBER = 1<<OPTBIT_UPTO_NUMBER, |
| 396 | #define OPT_NEXT_OTHER (1<<(5+OPT_INC_P+OPT_INC_X+OPT_INC_0)) | 379 | OPT_UPTO_SIZE = 1<<OPTBIT_UPTO_SIZE , |
| 397 | */ | 380 | OPT_EOF_STRING = 1<<OPTBIT_EOF_STRING , |
| 381 | OPT_INTERACTIVE = USE_FEATURE_XARGS_SUPPORT_CONFIRMATION((1<<OPTBIT_INTERACTIVE)) + 0, | ||
| 382 | OPT_TERMINATE = USE_FEATURE_XARGS_SUPPORT_TERMOPT( (1<<OPTBIT_TERMINATE )) + 0, | ||
| 383 | OPT_ZEROTERM = USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1<<OPTBIT_ZEROTERM )) + 0, | ||
| 384 | }; | ||
| 385 | #define OPTION_STR "+trn:s:e::" \ | ||
| 386 | USE_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ | ||
| 387 | USE_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ | ||
| 388 | USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") | ||
| 398 | 389 | ||
| 399 | int xargs_main(int argc, char **argv) | 390 | int xargs_main(int argc, char **argv) |
| 400 | { | 391 | { |
| 401 | char **args; | 392 | char **args; |
| 402 | int i, a, n; | 393 | int i, n; |
| 403 | xlist_t *list = NULL; | 394 | xlist_t *list = NULL; |
| 404 | xlist_t *cur; | 395 | xlist_t *cur; |
| 405 | int child_error = 0; | 396 | int child_error = 0; |
| @@ -410,42 +401,33 @@ int xargs_main(int argc, char **argv) | |||
| 410 | const char *eof_str = "_"; | 401 | const char *eof_str = "_"; |
| 411 | unsigned long opt; | 402 | unsigned long opt; |
| 412 | size_t n_max_chars; | 403 | size_t n_max_chars; |
| 413 | 404 | #if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM | |
| 414 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM | 405 | xlist_t* (*read_args)(xlist_t*, const char*, size_t, char*) = process_stdin; |
| 415 | xlist_t *(*read_args) (xlist_t *, const char *, size_t, char *) = process_stdin; | 406 | #else |
| 407 | #define read_args process_stdin | ||
| 416 | #endif | 408 | #endif |
| 417 | 409 | ||
| 418 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION | 410 | opt = bb_getopt_ulflags(argc, argv, OPTION_STR, &max_args, &max_chars, &eof_str); |
| 419 | bb_opt_complementally = "pt"; | ||
| 420 | #endif | ||
| 421 | 411 | ||
| 422 | opt = bb_getopt_ulflags(argc, argv, "+trn:s:e::" | 412 | if (opt & OPT_ZEROTERM) |
| 423 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION | 413 | USE_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin); |
| 424 | "p" | ||
| 425 | #endif | ||
| 426 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT | ||
| 427 | "x" | ||
| 428 | #endif | ||
| 429 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM | ||
| 430 | "0" | ||
| 431 | #endif | ||
| 432 | ,&max_args, &max_chars, &eof_str); | ||
| 433 | 414 | ||
| 434 | a = argc - optind; | 415 | argc -= optind; |
| 435 | argv += optind; | 416 | argv += optind; |
| 436 | if (a == 0) { | 417 | if (!argc) { |
| 437 | /* default behavior is to echo all the filenames */ | 418 | /* default behavior is to echo all the filenames */ |
| 438 | *argv = "echo"; | 419 | *argv = "echo"; |
| 439 | a++; | 420 | argc++; |
| 440 | } | 421 | } |
| 441 | 422 | ||
| 442 | orig_arg_max = ARG_MAX; | 423 | orig_arg_max = ARG_MAX; |
| 443 | if (orig_arg_max == -1) | 424 | if (orig_arg_max == -1) |
| 444 | orig_arg_max = LONG_MAX; | 425 | orig_arg_max = LONG_MAX; |
| 445 | orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048. */ | 426 | orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048 */ |
| 446 | if ((opt & OPT_UPTO_SIZE)) { | 427 | |
| 428 | if (opt & OPT_UPTO_SIZE) { | ||
| 447 | n_max_chars = bb_xgetularg10_bnd(max_chars, 1, orig_arg_max); | 429 | n_max_chars = bb_xgetularg10_bnd(max_chars, 1, orig_arg_max); |
| 448 | for (i = 0; i < a; i++) { | 430 | for (i = 0; i < argc; i++) { |
| 449 | n_chars += strlen(*argv) + 1; | 431 | n_chars += strlen(*argv) + 1; |
| 450 | } | 432 | } |
| 451 | if (n_max_chars < n_chars) { | 433 | if (n_max_chars < n_chars) { |
| @@ -463,19 +445,14 @@ int xargs_main(int argc, char **argv) | |||
| 463 | } | 445 | } |
| 464 | max_chars = xmalloc(n_max_chars); | 446 | max_chars = xmalloc(n_max_chars); |
| 465 | 447 | ||
| 466 | if ((opt & OPT_UPTO_NUMBER)) { | 448 | if (opt & OPT_UPTO_NUMBER) { |
| 467 | n_max_arg = bb_xgetularg10_bnd(max_args, 1, INT_MAX); | 449 | n_max_arg = bb_xgetularg10_bnd(max_args, 1, INT_MAX); |
| 468 | } else { | 450 | } else { |
| 469 | n_max_arg = n_max_chars; | 451 | n_max_arg = n_max_chars; |
| 470 | } | 452 | } |
| 471 | 453 | ||
| 472 | #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM | 454 | while ((list = read_args(list, eof_str, n_max_chars, max_chars)) != NULL || |
| 473 | if (opt & OPT_ZEROTERM) | 455 | !(opt & OPT_NO_EMPTY)) |
| 474 | read_args = process0_stdin; | ||
| 475 | #endif | ||
| 476 | |||
| 477 | while ((list = READ_ARGS(list, eof_str, n_max_chars, max_chars)) != NULL || | ||
| 478 | (opt & OPT_NO_EMPTY) == 0) | ||
| 479 | { | 456 | { |
| 480 | opt |= OPT_NO_EMPTY; | 457 | opt |= OPT_NO_EMPTY; |
| 481 | n = 0; | 458 | n = 0; |
| @@ -501,13 +478,13 @@ int xargs_main(int argc, char **argv) | |||
| 501 | } | 478 | } |
| 502 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT */ | 479 | #endif /* CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT */ |
| 503 | 480 | ||
| 504 | /* allocating pointers for execvp: | 481 | /* allocate pointers for execvp: |
| 505 | a*arg, n*arg from stdin, NULL */ | 482 | argc*arg, n*arg from stdin, NULL */ |
| 506 | args = xzalloc((n + a + 1) * sizeof(char *)); | 483 | args = xzalloc((n + argc + 1) * sizeof(char *)); |
| 507 | 484 | ||
| 508 | /* Store the command to be executed | 485 | /* store the command to be executed |
| 509 | (taken from the command line) */ | 486 | (taken from the command line) */ |
| 510 | for (i = 0; i < a; i++) | 487 | for (i = 0; i < argc; i++) |
| 511 | args[i] = argv[i]; | 488 | args[i] = argv[i]; |
| 512 | /* (taken from stdin) */ | 489 | /* (taken from stdin) */ |
| 513 | for (cur = list; n; cur = cur->link) { | 490 | for (cur = list; n; cur = cur->link) { |
| @@ -515,21 +492,21 @@ int xargs_main(int argc, char **argv) | |||
| 515 | n--; | 492 | n--; |
| 516 | } | 493 | } |
| 517 | 494 | ||
| 518 | if ((opt & (OPT_INTERACTIVE | OPT_VERBOSE))) { | 495 | if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) { |
| 519 | for (i = 0; args[i]; i++) { | 496 | for (i = 0; args[i]; i++) { |
| 520 | if (i) | 497 | if (i) |
| 521 | fputc(' ', stderr); | 498 | fputc(' ', stderr); |
| 522 | fputs(args[i], stderr); | 499 | fputs(args[i], stderr); |
| 523 | } | 500 | } |
| 524 | if ((opt & OPT_INTERACTIVE) == 0) | 501 | if (!(opt & OPT_INTERACTIVE)) |
| 525 | fputc('\n', stderr); | 502 | fputc('\n', stderr); |
| 526 | } | 503 | } |
| 527 | if ((opt & OPT_INTERACTIVE) == 0 || xargs_ask_confirmation() != 0) { | 504 | if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) { |
| 528 | child_error = xargs_exec(args); | 505 | child_error = xargs_exec(args); |
| 529 | } | 506 | } |
| 530 | 507 | ||
| 531 | /* clean up */ | 508 | /* clean up */ |
| 532 | for (i = a; args[i]; i++) { | 509 | for (i = argc; args[i]; i++) { |
| 533 | cur = list; | 510 | cur = list; |
| 534 | list = list->link; | 511 | list = list->link; |
| 535 | free(cur); | 512 | free(cur); |
| @@ -539,9 +516,7 @@ int xargs_main(int argc, char **argv) | |||
| 539 | break; | 516 | break; |
| 540 | } | 517 | } |
| 541 | } | 518 | } |
| 542 | #ifdef CONFIG_FEATURE_CLEAN_UP | 519 | if (ENABLE_FEATURE_CLEAN_UP) free(max_chars); |
| 543 | free(max_chars); | ||
| 544 | #endif | ||
| 545 | return child_error; | 520 | return child_error; |
| 546 | } | 521 | } |
| 547 | 522 | ||
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c index 941e3c96e..edc6a78bb 100644 --- a/libbb/getopt_ulflags.c +++ b/libbb/getopt_ulflags.c | |||
| @@ -91,6 +91,7 @@ const struct option *bb_applet_long_options | |||
| 91 | is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS. | 91 | is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS. |
| 92 | 92 | ||
| 93 | const char *bb_opt_complementally | 93 | const char *bb_opt_complementally |
| 94 | |||
| 94 | this should be bb_opt_complementary, but we'll just keep it as | 95 | this should be bb_opt_complementary, but we'll just keep it as |
| 95 | bb_opt_complementally due to the Russian origins | 96 | bb_opt_complementally due to the Russian origins |
| 96 | 97 | ||
