diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-18 22:22:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-18 22:22:04 +0200 |
commit | bf4aeed129ba7518be04ab9e53073bdb737a24b8 (patch) | |
tree | 3a98fa58c9d7fc378560b9717c44a97d30c3edfd /coreutils | |
parent | c9f280cc469daccfc0eba20bca6a1341070230b6 (diff) | |
download | busybox-w32-bf4aeed129ba7518be04ab9e53073bdb737a24b8.tar.gz busybox-w32-bf4aeed129ba7518be04ab9e53073bdb737a24b8.tar.bz2 busybox-w32-bf4aeed129ba7518be04ab9e53073bdb737a24b8.zip |
printf: fix exit code on conversion error
Signed-off-by: Colin Watson <cjwatson@ubuntu.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/printf.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index 2beea7189..5b326c643 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -53,10 +53,7 @@ | |||
53 | * (but negative numbers are not "bad"). | 53 | * (but negative numbers are not "bad"). |
54 | * Both accept negative numbers for %u specifier. | 54 | * Both accept negative numbers for %u specifier. |
55 | * | 55 | * |
56 | * We try to be compatible. We are not compatible here: | 56 | * We try to be compatible. |
57 | * - we do not accept -NUM for %u | ||
58 | * - exit code is 0 even if "invalid number" was seen (FIXME) | ||
59 | * See "if (errno)" checks in the code below. | ||
60 | */ | 57 | */ |
61 | 58 | ||
62 | typedef void FAST_FUNC (*converter)(const char *arg, void *result); | 59 | typedef void FAST_FUNC (*converter)(const char *arg, void *result); |
@@ -163,7 +160,6 @@ static void print_direc(char *format, unsigned fmt_length, | |||
163 | case 'i': | 160 | case 'i': |
164 | llv = my_xstrtoll(argument); | 161 | llv = my_xstrtoll(argument); |
165 | print_long: | 162 | print_long: |
166 | /* if (errno) return; - see comment at the top */ | ||
167 | if (!have_width) { | 163 | if (!have_width) { |
168 | if (!have_prec) | 164 | if (!have_prec) |
169 | printf(format, llv); | 165 | printf(format, llv); |
@@ -210,7 +206,6 @@ static void print_direc(char *format, unsigned fmt_length, | |||
210 | case 'g': | 206 | case 'g': |
211 | case 'G': | 207 | case 'G': |
212 | dv = my_xstrtod(argument); | 208 | dv = my_xstrtod(argument); |
213 | /* if (errno) return; */ | ||
214 | if (!have_width) { | 209 | if (!have_width) { |
215 | if (!have_prec) | 210 | if (!have_prec) |
216 | printf(format, dv); | 211 | printf(format, dv); |
@@ -241,7 +236,7 @@ static int get_width_prec(const char *str) | |||
241 | 236 | ||
242 | /* Print the text in FORMAT, using ARGV for arguments to any '%' directives. | 237 | /* Print the text in FORMAT, using ARGV for arguments to any '%' directives. |
243 | Return advanced ARGV. */ | 238 | Return advanced ARGV. */ |
244 | static char **print_formatted(char *f, char **argv) | 239 | static char **print_formatted(char *f, char **argv, int *conv_err) |
245 | { | 240 | { |
246 | char *direc_start; /* Start of % directive. */ | 241 | char *direc_start; /* Start of % directive. */ |
247 | unsigned direc_length; /* Length of % directive. */ | 242 | unsigned direc_length; /* Length of % directive. */ |
@@ -299,8 +294,8 @@ static char **print_formatted(char *f, char **argv) | |||
299 | 294 | ||
300 | /* Remove "lLhz" size modifiers, repeatedly. | 295 | /* Remove "lLhz" size modifiers, repeatedly. |
301 | * bash does not like "%lld", but coreutils | 296 | * bash does not like "%lld", but coreutils |
302 | * would happily take even "%Llllhhzhhzd"! | 297 | * happily takes even "%Llllhhzhhzd"! |
303 | * We will be permissive like coreutils */ | 298 | * We are permissive like coreutils */ |
304 | while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') { | 299 | while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') { |
305 | overlapping_strcpy(f, f + 1); | 300 | overlapping_strcpy(f, f + 1); |
306 | } | 301 | } |
@@ -330,12 +325,12 @@ static char **print_formatted(char *f, char **argv) | |||
330 | } | 325 | } |
331 | if (*argv) { | 326 | if (*argv) { |
332 | print_direc(direc_start, direc_length, field_width, | 327 | print_direc(direc_start, direc_length, field_width, |
333 | precision, *argv); | 328 | precision, *argv++); |
334 | ++argv; | ||
335 | } else { | 329 | } else { |
336 | print_direc(direc_start, direc_length, field_width, | 330 | print_direc(direc_start, direc_length, field_width, |
337 | precision, ""); | 331 | precision, ""); |
338 | } | 332 | } |
333 | *conv_err |= errno; | ||
339 | free(p); | 334 | free(p); |
340 | } | 335 | } |
341 | break; | 336 | break; |
@@ -356,6 +351,7 @@ static char **print_formatted(char *f, char **argv) | |||
356 | 351 | ||
357 | int printf_main(int argc UNUSED_PARAM, char **argv) | 352 | int printf_main(int argc UNUSED_PARAM, char **argv) |
358 | { | 353 | { |
354 | int conv_err; | ||
359 | char *format; | 355 | char *format; |
360 | char **argv2; | 356 | char **argv2; |
361 | 357 | ||
@@ -392,9 +388,10 @@ int printf_main(int argc UNUSED_PARAM, char **argv) | |||
392 | format = argv[1]; | 388 | format = argv[1]; |
393 | argv2 = argv + 2; | 389 | argv2 = argv + 2; |
394 | 390 | ||
391 | conv_err = 0; | ||
395 | do { | 392 | do { |
396 | argv = argv2; | 393 | argv = argv2; |
397 | argv2 = print_formatted(format, argv); | 394 | argv2 = print_formatted(format, argv, &conv_err); |
398 | } while (argv2 > argv && *argv2); | 395 | } while (argv2 > argv && *argv2); |
399 | 396 | ||
400 | /* coreutils compat (bash doesn't do this): | 397 | /* coreutils compat (bash doesn't do this): |
@@ -402,5 +399,6 @@ int printf_main(int argc UNUSED_PARAM, char **argv) | |||
402 | fprintf(stderr, "excess args ignored"); | 399 | fprintf(stderr, "excess args ignored"); |
403 | */ | 400 | */ |
404 | 401 | ||
405 | return (argv2 < argv); /* if true, print_formatted errored out */ | 402 | return (argv2 < argv) /* if true, print_formatted errored out */ |
403 | || conv_err; /* print_formatted saw invalid number */ | ||
406 | } | 404 | } |