printf: fix exit code on conversion error
Signed-off-by: Colin Watson <cjwatson@ubuntu.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
c9f280cc46
commit
bf4aeed129
@ -53,10 +53,7 @@
|
||||
* (but negative numbers are not "bad").
|
||||
* Both accept negative numbers for %u specifier.
|
||||
*
|
||||
* We try to be compatible. We are not compatible here:
|
||||
* - we do not accept -NUM for %u
|
||||
* - exit code is 0 even if "invalid number" was seen (FIXME)
|
||||
* See "if (errno)" checks in the code below.
|
||||
* We try to be compatible.
|
||||
*/
|
||||
|
||||
typedef void FAST_FUNC (*converter)(const char *arg, void *result);
|
||||
@ -163,7 +160,6 @@ static void print_direc(char *format, unsigned fmt_length,
|
||||
case 'i':
|
||||
llv = my_xstrtoll(argument);
|
||||
print_long:
|
||||
/* if (errno) return; - see comment at the top */
|
||||
if (!have_width) {
|
||||
if (!have_prec)
|
||||
printf(format, llv);
|
||||
@ -210,7 +206,6 @@ static void print_direc(char *format, unsigned fmt_length,
|
||||
case 'g':
|
||||
case 'G':
|
||||
dv = my_xstrtod(argument);
|
||||
/* if (errno) return; */
|
||||
if (!have_width) {
|
||||
if (!have_prec)
|
||||
printf(format, dv);
|
||||
@ -241,7 +236,7 @@ static int get_width_prec(const char *str)
|
||||
|
||||
/* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
|
||||
Return advanced ARGV. */
|
||||
static char **print_formatted(char *f, char **argv)
|
||||
static char **print_formatted(char *f, char **argv, int *conv_err)
|
||||
{
|
||||
char *direc_start; /* Start of % directive. */
|
||||
unsigned direc_length; /* Length of % directive. */
|
||||
@ -299,8 +294,8 @@ static char **print_formatted(char *f, char **argv)
|
||||
|
||||
/* Remove "lLhz" size modifiers, repeatedly.
|
||||
* bash does not like "%lld", but coreutils
|
||||
* would happily take even "%Llllhhzhhzd"!
|
||||
* We will be permissive like coreutils */
|
||||
* happily takes even "%Llllhhzhhzd"!
|
||||
* We are permissive like coreutils */
|
||||
while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
|
||||
overlapping_strcpy(f, f + 1);
|
||||
}
|
||||
@ -330,12 +325,12 @@ static char **print_formatted(char *f, char **argv)
|
||||
}
|
||||
if (*argv) {
|
||||
print_direc(direc_start, direc_length, field_width,
|
||||
precision, *argv);
|
||||
++argv;
|
||||
precision, *argv++);
|
||||
} else {
|
||||
print_direc(direc_start, direc_length, field_width,
|
||||
precision, "");
|
||||
}
|
||||
*conv_err |= errno;
|
||||
free(p);
|
||||
}
|
||||
break;
|
||||
@ -356,6 +351,7 @@ static char **print_formatted(char *f, char **argv)
|
||||
|
||||
int printf_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
int conv_err;
|
||||
char *format;
|
||||
char **argv2;
|
||||
|
||||
@ -392,9 +388,10 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
|
||||
format = argv[1];
|
||||
argv2 = argv + 2;
|
||||
|
||||
conv_err = 0;
|
||||
do {
|
||||
argv = argv2;
|
||||
argv2 = print_formatted(format, argv);
|
||||
argv2 = print_formatted(format, argv, &conv_err);
|
||||
} while (argv2 > argv && *argv2);
|
||||
|
||||
/* coreutils compat (bash doesn't do this):
|
||||
@ -402,5 +399,6 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
|
||||
fprintf(stderr, "excess args ignored");
|
||||
*/
|
||||
|
||||
return (argv2 < argv); /* if true, print_formatted errored out */
|
||||
return (argv2 < argv) /* if true, print_formatted errored out */
|
||||
|| conv_err; /* print_formatted saw invalid number */
|
||||
}
|
||||
|
@ -87,13 +87,12 @@ testing "printf understands %Ld" \
|
||||
# "1\n""printf: -2: invalid number\n""0\n""3\n""0\n" \
|
||||
# "" ""
|
||||
|
||||
# Actually, we are wrong here: exit code should be 1
|
||||
testing "printf handles %d bad_input" \
|
||||
"${bb}printf '%d\n' 1 - 2 bad 3 123bad 4 2>&1; echo \$?" \
|
||||
"1\n""printf: -: invalid number\n""0\n"\
|
||||
"2\n""printf: bad: invalid number\n""0\n"\
|
||||
"3\n""printf: 123bad: invalid number\n""0\n"\
|
||||
"4\n""0\n" \
|
||||
"4\n""1\n" \
|
||||
"" ""
|
||||
|
||||
testing "printf aborts on bare %" \
|
||||
|
Loading…
Reference in New Issue
Block a user