xargs: fix accounting of -sNUM
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
1613de85d9
commit
aaa24e09f9
@ -89,9 +89,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This function has special algorithm.
|
* This function has special algorithm.
|
||||||
Don't use fork and include to main!
|
* Don't use fork and include to main!
|
||||||
*/
|
*/
|
||||||
static int xargs_exec(char **args)
|
static int xargs_exec(char **args)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
@ -118,7 +118,7 @@ static int xargs_exec(char **args)
|
|||||||
|
|
||||||
typedef struct xlist_t {
|
typedef struct xlist_t {
|
||||||
struct xlist_t *link;
|
struct xlist_t *link;
|
||||||
size_t length;
|
size_t length; /* length of xstr[] including NUL */
|
||||||
char xstr[1];
|
char xstr[1];
|
||||||
} xlist_t;
|
} xlist_t;
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ typedef struct xlist_t {
|
|||||||
|
|
||||||
#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
|
#if ENABLE_FEATURE_XARGS_SUPPORT_QUOTES
|
||||||
static xlist_t* process_stdin(xlist_t *list_arg,
|
static xlist_t* process_stdin(xlist_t *list_arg,
|
||||||
const char *eof_str, size_t mc, char *buf)
|
const char *eof_str, size_t n_max_chars, char *buf)
|
||||||
{
|
{
|
||||||
#define NORM 0
|
#define NORM 0
|
||||||
#define QUOTE 1
|
#define QUOTE 1
|
||||||
@ -187,7 +187,7 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
state = QUOTE;
|
state = QUOTE;
|
||||||
} else {
|
} else {
|
||||||
set:
|
set:
|
||||||
if ((size_t)(p - buf) >= mc)
|
if ((size_t)(p - buf) >= n_max_chars)
|
||||||
bb_error_msg_and_die("argument line too long");
|
bb_error_msg_and_die("argument line too long");
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
prev = cur;
|
prev = cur;
|
||||||
line_l += length;
|
line_l += length;
|
||||||
if (line_l > mc) /* limit stop memory usage */
|
if (line_l >= n_max_chars) /* limit memory usage */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s = NULL;
|
s = NULL;
|
||||||
@ -228,7 +228,7 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
#else
|
#else
|
||||||
/* The variant does not support single quotes, double quotes or backslash */
|
/* The variant does not support single quotes, double quotes or backslash */
|
||||||
static xlist_t* process_stdin(xlist_t *list_arg,
|
static xlist_t* process_stdin(xlist_t *list_arg,
|
||||||
const char *eof_str, size_t mc, char *buf)
|
const char *eof_str, size_t n_max_chars, char *buf)
|
||||||
{
|
{
|
||||||
char eof_str_detected = 0;
|
char eof_str_detected = 0;
|
||||||
char *s = NULL; /* start of the word */
|
char *s = NULL; /* start of the word */
|
||||||
@ -260,7 +260,7 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
s = p = buf;
|
s = p = buf;
|
||||||
if ((size_t)(p - buf) >= mc)
|
if ((size_t)(p - buf) >= n_max_chars)
|
||||||
bb_error_msg_and_die("argument line too long");
|
bb_error_msg_and_die("argument line too long");
|
||||||
*p++ = (c == EOF ? '\0' : c);
|
*p++ = (c == EOF ? '\0' : c);
|
||||||
if (c == EOF) { /* word's delimiter or EOF detected */
|
if (c == EOF) { /* word's delimiter or EOF detected */
|
||||||
@ -282,7 +282,7 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
prev = cur;
|
prev = cur;
|
||||||
line_l += length;
|
line_l += length;
|
||||||
if (line_l > mc) /* limit stop memory usage */
|
if (line_l >= n_max_chars) /* limit memory usage */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s = NULL;
|
s = NULL;
|
||||||
@ -292,32 +292,9 @@ static xlist_t* process_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
#endif /* FEATURE_XARGS_SUPPORT_QUOTES */
|
#endif /* FEATURE_XARGS_SUPPORT_QUOTES */
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_XARGS_SUPPORT_CONFIRMATION
|
|
||||||
/* Prompt the user for a response, and
|
|
||||||
if the user responds affirmatively, return true;
|
|
||||||
otherwise, return false. Uses "/dev/tty", not stdin. */
|
|
||||||
static int xargs_ask_confirmation(void)
|
|
||||||
{
|
|
||||||
FILE *tty_stream;
|
|
||||||
int c, savec;
|
|
||||||
|
|
||||||
tty_stream = xfopen_for_read(CURRENT_TTY);
|
|
||||||
fputs(" ?...", stderr);
|
|
||||||
fflush_all();
|
|
||||||
c = savec = getc(tty_stream);
|
|
||||||
while (c != EOF && c != '\n')
|
|
||||||
c = getc(tty_stream);
|
|
||||||
fclose(tty_stream);
|
|
||||||
return (savec == 'y' || savec == 'Y');
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define xargs_ask_confirmation() 1
|
|
||||||
#endif /* FEATURE_XARGS_SUPPORT_CONFIRMATION */
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM
|
#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM
|
||||||
static xlist_t* process0_stdin(xlist_t *list_arg,
|
static xlist_t* process0_stdin(xlist_t *list_arg,
|
||||||
const char *eof_str UNUSED_PARAM, size_t mc, char *buf)
|
const char *eof_str UNUSED_PARAM, size_t n_max_chars, char *buf)
|
||||||
{
|
{
|
||||||
char *s = NULL; /* start of the word */
|
char *s = NULL; /* start of the word */
|
||||||
char *p = NULL; /* pointer to end of the word */
|
char *p = NULL; /* pointer to end of the word */
|
||||||
@ -341,7 +318,7 @@ static xlist_t* process0_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
s = p = buf;
|
s = p = buf;
|
||||||
if ((size_t)(p - buf) >= mc)
|
if ((size_t)(p - buf) >= n_max_chars)
|
||||||
bb_error_msg_and_die("argument line too long");
|
bb_error_msg_and_die("argument line too long");
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
if (c == '\0') { /* word's delimiter or EOF detected */
|
if (c == '\0') { /* word's delimiter or EOF detected */
|
||||||
@ -359,7 +336,7 @@ static xlist_t* process0_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
prev = cur;
|
prev = cur;
|
||||||
line_l += length;
|
line_l += length;
|
||||||
if (line_l > mc) /* limit stop memory usage */
|
if (line_l >= n_max_chars) /* limit memory usage */
|
||||||
break;
|
break;
|
||||||
s = NULL;
|
s = NULL;
|
||||||
}
|
}
|
||||||
@ -368,6 +345,28 @@ static xlist_t* process0_stdin(xlist_t *list_arg,
|
|||||||
}
|
}
|
||||||
#endif /* FEATURE_XARGS_SUPPORT_ZERO_TERM */
|
#endif /* FEATURE_XARGS_SUPPORT_ZERO_TERM */
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_XARGS_SUPPORT_CONFIRMATION
|
||||||
|
/* Prompt the user for a response, and
|
||||||
|
if the user responds affirmatively, return true;
|
||||||
|
otherwise, return false. Uses "/dev/tty", not stdin. */
|
||||||
|
static int xargs_ask_confirmation(void)
|
||||||
|
{
|
||||||
|
FILE *tty_stream;
|
||||||
|
int c, savec;
|
||||||
|
|
||||||
|
tty_stream = xfopen_for_read(CURRENT_TTY);
|
||||||
|
fputs(" ?...", stderr);
|
||||||
|
fflush_all();
|
||||||
|
c = savec = getc(tty_stream);
|
||||||
|
while (c != EOF && c != '\n')
|
||||||
|
c = getc(tty_stream);
|
||||||
|
fclose(tty_stream);
|
||||||
|
return (savec == 'y' || savec == 'Y');
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define xargs_ask_confirmation() 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Correct regardless of combination of CONFIG_xxx */
|
/* Correct regardless of combination of CONFIG_xxx */
|
||||||
enum {
|
enum {
|
||||||
OPTBIT_VERBOSE = 0,
|
OPTBIT_VERBOSE = 0,
|
||||||
@ -468,9 +467,11 @@ int xargs_main(int argc, char **argv)
|
|||||||
|
|
||||||
if (opt & OPT_UPTO_NUMBER) {
|
if (opt & OPT_UPTO_NUMBER) {
|
||||||
n_max_arg = xatoul_range(max_args, 1, INT_MAX);
|
n_max_arg = xatoul_range(max_args, 1, INT_MAX);
|
||||||
} else {
|
if (n_max_arg < n_max_chars)
|
||||||
n_max_arg = n_max_chars;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
n_max_arg = n_max_chars;
|
||||||
|
skip:
|
||||||
|
|
||||||
while ((list = read_args(list, eof_str, n_max_chars, buf)) != NULL
|
while ((list = read_args(list, eof_str, n_max_chars, buf)) != NULL
|
||||||
|| !(opt & OPT_NO_EMPTY)
|
|| !(opt & OPT_NO_EMPTY)
|
||||||
@ -478,30 +479,22 @@ int xargs_main(int argc, char **argv)
|
|||||||
char **args;
|
char **args;
|
||||||
xlist_t *cur;
|
xlist_t *cur;
|
||||||
int i, n;
|
int i, n;
|
||||||
size_t n_chars = 0;
|
size_t n_chars;
|
||||||
|
|
||||||
opt |= OPT_NO_EMPTY;
|
opt |= OPT_NO_EMPTY;
|
||||||
|
|
||||||
|
/* take args from list, not exceeding arg and char limits */
|
||||||
|
n_chars = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
#if ENABLE_FEATURE_XARGS_SUPPORT_TERMOPT
|
for (cur = list; cur; cur = cur->link) {
|
||||||
for (cur = list; cur;) {
|
|
||||||
n_chars += cur->length;
|
n_chars += cur->length;
|
||||||
n++;
|
if (n_chars > n_max_chars || n >= n_max_arg) {
|
||||||
cur = cur->link;
|
|
||||||
if (n_chars > n_max_chars || (n == n_max_arg && cur)) {
|
|
||||||
if (opt & OPT_TERMINATE)
|
if (opt & OPT_TERMINATE)
|
||||||
bb_error_msg_and_die("argument list too long");
|
bb_error_msg_and_die("argument list too long");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (cur = list; cur; cur = cur->link) {
|
|
||||||
n_chars += cur->length;
|
|
||||||
n++;
|
n++;
|
||||||
if (n_chars > n_max_chars || n == n_max_arg) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* allocate pointers for execvp */
|
/* allocate pointers for execvp */
|
||||||
args = xzalloc(sizeof(args[0]) * (argc + n + 1));
|
args = xzalloc(sizeof(args[0]) * (argc + n + 1));
|
||||||
@ -530,7 +523,7 @@ int xargs_main(int argc, char **argv)
|
|||||||
child_error = xargs_exec(args);
|
child_error = xargs_exec(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up */
|
/* remove list elements which we consumed */
|
||||||
for (i = argc; args[i]; i++) {
|
for (i = argc; args[i]; i++) {
|
||||||
cur = list;
|
cur = list;
|
||||||
list = list->link;
|
list = list->link;
|
||||||
|
@ -27,8 +27,18 @@ testing "xargs does not stop on underscore ('new' GNU behavior)" \
|
|||||||
"" "a\n_\nb\n"
|
"" "a\n_\nb\n"
|
||||||
|
|
||||||
testing "xargs -s7 can take one-char input" \
|
testing "xargs -s7 can take one-char input" \
|
||||||
"xargs -s7" \
|
"xargs -s7 echo" \
|
||||||
"a\n" \
|
"a\n" \
|
||||||
"" "a\n"
|
"" "a\n"
|
||||||
|
|
||||||
|
testing "xargs -sNUM test 1" \
|
||||||
|
"xargs -ts25 echo 2>&1 >/dev/null" \
|
||||||
|
"echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 00\n" \
|
||||||
|
"" "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 00\n"
|
||||||
|
|
||||||
|
testing "xargs -sNUM test 2" \
|
||||||
|
"xargs -ts25 echo 1 2>&1 >/dev/null" \
|
||||||
|
"echo 1 2 3 4 5 6 7 8 9 0\n""echo 1 2 3 4 5 6 7 8 9\n""echo 1 00\n" \
|
||||||
|
"" "2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 00\n"
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user