diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 14:58:40 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 14:58:40 +0200 |
commit | d7b5289209131ae94b540b35f0f147d2302ec0c9 (patch) | |
tree | 99f42a344c1216060dc7fe8347c5e1773d1e0d52 | |
parent | 125d0154e6c591addbaf1fae7c9ffdf5b7e7ed7b (diff) | |
download | busybox-w32-d7b5289209131ae94b540b35f0f147d2302ec0c9.tar.gz busybox-w32-d7b5289209131ae94b540b35f0f147d2302ec0c9.tar.bz2 busybox-w32-d7b5289209131ae94b540b35f0f147d2302ec0c9.zip |
xargs: do not decrease orig_arg_max to negative values
Based on patch by Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | findutils/xargs.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c index f5dbc7825..3785f1ec0 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -25,10 +25,10 @@ | |||
25 | /* COMPAT: SYSV version defaults size (and has a max value of) to 470. | 25 | /* COMPAT: SYSV version defaults size (and has a max value of) to 470. |
26 | We try to make it as large as possible. */ | 26 | We try to make it as large as possible. */ |
27 | #if !defined(ARG_MAX) && defined(_SC_ARG_MAX) | 27 | #if !defined(ARG_MAX) && defined(_SC_ARG_MAX) |
28 | #define ARG_MAX sysconf (_SC_ARG_MAX) | 28 | # define ARG_MAX sysconf(_SC_ARG_MAX) |
29 | #endif | 29 | #endif |
30 | #ifndef ARG_MAX | 30 | #if !defined(ARG_MAX) |
31 | #define ARG_MAX 470 | 31 | # define ARG_MAX 470 |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | 34 | ||
@@ -378,8 +378,6 @@ int xargs_main(int argc, char **argv) | |||
378 | int child_error = 0; | 378 | int child_error = 0; |
379 | char *max_args, *max_chars; | 379 | char *max_args, *max_chars; |
380 | int n_max_arg; | 380 | int n_max_arg; |
381 | size_t n_chars = 0; | ||
382 | long orig_arg_max; | ||
383 | const char *eof_str = NULL; | 381 | const char *eof_str = NULL; |
384 | unsigned opt; | 382 | unsigned opt; |
385 | size_t n_max_chars; | 383 | size_t n_max_chars; |
@@ -408,28 +406,35 @@ int xargs_main(int argc, char **argv) | |||
408 | argc++; | 406 | argc++; |
409 | } | 407 | } |
410 | 408 | ||
411 | orig_arg_max = ARG_MAX; | 409 | n_max_chars = ARG_MAX; /* might be calling sysconf(_SC_ARG_MAX) */ |
412 | if (orig_arg_max == -1) | 410 | if (n_max_chars < 4*1024); /* paranoia */ |
413 | orig_arg_max = LONG_MAX; | 411 | n_max_chars = LONG_MAX; |
414 | orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048 */ | 412 | /* The Open Group Base Specifications Issue 6: |
413 | * "The xargs utility shall limit the command line length such that | ||
414 | * when the command line is invoked, the combined argument | ||
415 | * and environment lists (see the exec family of functions | ||
416 | * in the System Interfaces volume of IEEE Std 1003.1-2001) | ||
417 | * shall not exceed {ARG_MAX}-2048 bytes". | ||
418 | */ | ||
419 | n_max_chars -= 2048; | ||
420 | /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which | ||
421 | * have it at 1 meg). Things will work fine with a large ARG_MAX but it | ||
422 | * will probably hurt the system more than it needs to; an array of this | ||
423 | * size is allocated. | ||
424 | */ | ||
425 | if (n_max_chars > 20 * 1024) | ||
426 | n_max_chars = 20 * 1024; | ||
415 | 427 | ||
416 | if (opt & OPT_UPTO_SIZE) { | 428 | if (opt & OPT_UPTO_SIZE) { |
417 | n_max_chars = xatoul_range(max_chars, 1, orig_arg_max); | 429 | size_t n_chars = 0; |
430 | n_max_chars = xatoul_range(max_chars, 1, n_max_chars); | ||
418 | for (i = 0; i < argc; i++) { | 431 | for (i = 0; i < argc; i++) { |
419 | n_chars += strlen(*argv) + 1; | 432 | n_chars += strlen(*argv) + 1; |
420 | } | 433 | } |
421 | if (n_max_chars < n_chars) { | 434 | if (n_max_chars <= n_chars) { |
422 | bb_error_msg_and_die("can't fit single argument within argument list size limit"); | 435 | bb_error_msg_and_die("can't fit single argument within argument list size limit"); |
423 | } | 436 | } |
424 | n_max_chars -= n_chars; | 437 | n_max_chars -= n_chars; |
425 | } else { | ||
426 | /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which | ||
427 | have it at 1 meg). Things will work fine with a large ARG_MAX but it | ||
428 | will probably hurt the system more than it needs to; an array of this | ||
429 | size is allocated. */ | ||
430 | if (orig_arg_max > 20 * 1024) | ||
431 | orig_arg_max = 20 * 1024; | ||
432 | n_max_chars = orig_arg_max; | ||
433 | } | 438 | } |
434 | max_chars = xmalloc(n_max_chars); | 439 | max_chars = xmalloc(n_max_chars); |
435 | 440 | ||
@@ -442,9 +447,9 @@ int xargs_main(int argc, char **argv) | |||
442 | while ((list = read_args(list, eof_str, n_max_chars, max_chars)) != NULL || | 447 | while ((list = read_args(list, eof_str, n_max_chars, max_chars)) != NULL || |
443 | !(opt & OPT_NO_EMPTY)) | 448 | !(opt & OPT_NO_EMPTY)) |
444 | { | 449 | { |
450 | size_t n_chars = 0; | ||
445 | opt |= OPT_NO_EMPTY; | 451 | opt |= OPT_NO_EMPTY; |
446 | n = 0; | 452 | n = 0; |
447 | n_chars = 0; | ||
448 | #if ENABLE_FEATURE_XARGS_SUPPORT_TERMOPT | 453 | #if ENABLE_FEATURE_XARGS_SUPPORT_TERMOPT |
449 | for (cur = list; cur;) { | 454 | for (cur = list; cur;) { |
450 | n_chars += cur->length; | 455 | n_chars += cur->length; |