aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-08-20 00:12:22 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-08-20 00:12:22 +0000
commit1c45a505eb109af13e5399c2b016acec4ad10421 (patch)
tree589faea46f22af74b5ac7e4cc31e1ddae6f7d0c7
parent6c4eb4411305f61b3f96eefe0ebb147c7f8e6c6d (diff)
downloadbusybox-w32-1c45a505eb109af13e5399c2b016acec4ad10421.tar.gz
busybox-w32-1c45a505eb109af13e5399c2b016acec4ad10421.tar.bz2
busybox-w32-1c45a505eb109af13e5399c2b016acec4ad10421.zip
libbb: fix mishandling of "all argv are opts" in getopt32()
function old new delta top_main 1100 1095 -5 getopt32 1398 1361 -37 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-42) Total: -42 bytes
-rw-r--r--libbb/getopt32.c64
-rw-r--r--procps/top.c3
2 files changed, 25 insertions, 42 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 9dba44db2..611333c66 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -174,7 +174,7 @@ Special characters:
174 on the command line. 174 on the command line.
175 175
176 "V-" An option with dash before colon or end-of-line results in 176 "V-" An option with dash before colon or end-of-line results in
177 bb_show_usage being called if this option is encountered. 177 bb_show_usage() being called if this option is encountered.
178 This is typically used to implement "print verbose usage message 178 This is typically used to implement "print verbose usage message
179 and exit" option. 179 and exit" option.
180 180
@@ -285,10 +285,6 @@ const char *const bb_argv_dash[] = { "-", NULL };
285 285
286const char *opt_complementary; 286const char *opt_complementary;
287 287
288/* Many small applets don't want to suck in stdio.h only because
289 * they need to parse options by calling us */
290#define DONT_USE_PRINTF 1
291
292enum { 288enum {
293 PARAM_STRING, 289 PARAM_STRING,
294 PARAM_LIST, 290 PARAM_LIST,
@@ -322,7 +318,7 @@ getopt32(char **argv, const char *applet_opts, ...)
322 int argc; 318 int argc;
323 unsigned flags = 0; 319 unsigned flags = 0;
324 unsigned requires = 0; 320 unsigned requires = 0;
325 t_complementary complementary[33]; 321 t_complementary complementary[33]; /* last stays zero-filled */
326 int c; 322 int c;
327 const unsigned char *s; 323 const unsigned char *s;
328 t_complementary *on_off; 324 t_complementary *on_off;
@@ -332,14 +328,13 @@ getopt32(char **argv, const char *applet_opts, ...)
332 struct option *long_options = (struct option *) &bb_null_long_options; 328 struct option *long_options = (struct option *) &bb_null_long_options;
333#endif 329#endif
334 unsigned trigger; 330 unsigned trigger;
335 char **pargv = NULL; 331 char **pargv;
336 int min_arg = 0; 332 int min_arg = 0;
337 int max_arg = -1; 333 int max_arg = -1;
338 334
339#define SHOW_USAGE_IF_ERROR 1 335#define SHOW_USAGE_IF_ERROR 1
340#define ALL_ARGV_IS_OPTS 2 336#define ALL_ARGV_IS_OPTS 2
341#define FIRST_ARGV_IS_OPT 4 337#define FIRST_ARGV_IS_OPT 4
342#define FREE_FIRST_ARGV_IS_OPT (8 * !DONT_USE_PRINTF)
343 338
344 int spec_flgs = 0; 339 int spec_flgs = 0;
345 340
@@ -493,17 +488,18 @@ getopt32(char **argv, const char *applet_opts, ...)
493 } 488 }
494 va_end(p); 489 va_end(p);
495 490
496 if (spec_flgs & FIRST_ARGV_IS_OPT) { 491 if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) {
497 if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') { 492 pargv = argv + 1;
498#if DONT_USE_PRINTF 493 while (*pargv) {
499 char *pp = alloca(strlen(argv[1]) + 2); 494 if (pargv[0][0] != '-' && pargv[0][0] != '\0') {
500 *pp = '-'; 495 char *pp = alloca(strlen(*pargv) + 2);
501 strcpy(pp + 1, argv[1]); 496 *pp = '-';
502 argv[1] = pp; 497 strcpy(pp + 1, *pargv);
503#else 498 *pargv = pp;
504 argv[1] = xasprintf("-%s", argv[1]); 499 }
505 spec_flgs |= FREE_FIRST_ARGV_IS_OPT; 500 if (!(spec_flgs & ALL_ARGV_IS_OPTS))
506#endif 501 break;
502 pargv++;
507 } 503 }
508 } 504 }
509 505
@@ -529,6 +525,7 @@ getopt32(char **argv, const char *applet_opts, ...)
529 /* optreset = 1; */ 525 /* optreset = 1; */
530#endif 526#endif
531 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ 527 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
528 pargv = NULL;
532 529
533 /* Note: just "getopt() <= 0" will not work well for 530 /* Note: just "getopt() <= 0" will not work well for
534 * "fake" short options, like this one: 531 * "fake" short options, like this one:
@@ -540,12 +537,17 @@ getopt32(char **argv, const char *applet_opts, ...)
540#else 537#else
541 while ((c = getopt(argc, argv, applet_opts)) != -1) { 538 while ((c = getopt(argc, argv, applet_opts)) != -1) {
542#endif 539#endif
540 /* getopt prints "option requires an argument -- X"
541 * and returns '?' if an option has no arg, but one is reqd */
543 c &= 0xff; /* fight libc's sign extension */ 542 c &= 0xff; /* fight libc's sign extension */
544 loop_arg_is_opt:
545 for (on_off = complementary; on_off->opt_char != c; on_off++) { 543 for (on_off = complementary; on_off->opt_char != c; on_off++) {
546 /* c==0 if long opt have non NULL flag */ 544 /* c can be NUL if long opt has non-NULL ->flag,
547 if (on_off->opt_char == '\0' && c != '\0') 545 * but we construct long opts so that flag
546 * is always NULL (see above) */
547 if (on_off->opt_char == '\0' /* && c != '\0' */) {
548 /* c is probably '?' - "bad option" */
548 bb_show_usage(); 549 bb_show_usage();
550 }
549 } 551 }
550 if (flags & on_off->incongruously) 552 if (flags & on_off->incongruously)
551 bb_show_usage(); 553 bb_show_usage();
@@ -570,24 +572,6 @@ getopt32(char **argv, const char *applet_opts, ...)
570 break; 572 break;
571 } 573 }
572 574
573 if (spec_flgs & ALL_ARGV_IS_OPTS) {
574 /* process argv is option, for example "ps" applet */
575 if (pargv == NULL)
576 pargv = argv + optind;
577 while (*pargv) {
578 c = **pargv;
579 if (c == '\0') {
580 pargv++;
581 } else {
582 (*pargv)++;
583 goto loop_arg_is_opt;
584 }
585 }
586 }
587
588 if (spec_flgs & FREE_FIRST_ARGV_IS_OPT)
589 free(argv[1]);
590
591 /* check depending requires for given options */ 575 /* check depending requires for given options */
592 for (on_off = complementary; on_off->opt_char; on_off++) { 576 for (on_off = complementary; on_off->opt_char; on_off++) {
593 if (on_off->requires && (flags & on_off->switch_on) && 577 if (on_off->requires && (flags & on_off->switch_on) &&
diff --git a/procps/top.c b/procps/top.c
index 1f1415f83..663eac674 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -763,8 +763,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
763 763
764 /* all args are options; -n NUM */ 764 /* all args are options; -n NUM */
765 opt_complementary = "-:n+"; 765 opt_complementary = "-:n+";
766 getopt32(argv, "d:n:b", &sinterval, &iterations); 766 if (getopt32(argv, "d:n:b", &sinterval, &iterations) & OPT_d) {
767 if (option_mask32 & OPT_d) {
768 /* Need to limit it to not overflow poll timeout */ 767 /* Need to limit it to not overflow poll timeout */
769 interval = xatou16(sinterval); // -d 768 interval = xatou16(sinterval); // -d
770 } 769 }