printf: fix exit code on conversion error
No binary (build failed)
—
(log yok)
| @@ -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 %" \ | |