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
This commit is contained in:
parent
6c4eb44113
commit
1c45a505eb
@ -174,7 +174,7 @@ Special characters:
|
|||||||
on the command line.
|
on the command line.
|
||||||
|
|
||||||
"V-" An option with dash before colon or end-of-line results in
|
"V-" An option with dash before colon or end-of-line results in
|
||||||
bb_show_usage being called if this option is encountered.
|
bb_show_usage() being called if this option is encountered.
|
||||||
This is typically used to implement "print verbose usage message
|
This is typically used to implement "print verbose usage message
|
||||||
and exit" option.
|
and exit" option.
|
||||||
|
|
||||||
@ -285,10 +285,6 @@ const char *const bb_argv_dash[] = { "-", NULL };
|
|||||||
|
|
||||||
const char *opt_complementary;
|
const char *opt_complementary;
|
||||||
|
|
||||||
/* Many small applets don't want to suck in stdio.h only because
|
|
||||||
* they need to parse options by calling us */
|
|
||||||
#define DONT_USE_PRINTF 1
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PARAM_STRING,
|
PARAM_STRING,
|
||||||
PARAM_LIST,
|
PARAM_LIST,
|
||||||
@ -322,7 +318,7 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
int argc;
|
int argc;
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
unsigned requires = 0;
|
unsigned requires = 0;
|
||||||
t_complementary complementary[33];
|
t_complementary complementary[33]; /* last stays zero-filled */
|
||||||
int c;
|
int c;
|
||||||
const unsigned char *s;
|
const unsigned char *s;
|
||||||
t_complementary *on_off;
|
t_complementary *on_off;
|
||||||
@ -332,14 +328,13 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
struct option *long_options = (struct option *) &bb_null_long_options;
|
struct option *long_options = (struct option *) &bb_null_long_options;
|
||||||
#endif
|
#endif
|
||||||
unsigned trigger;
|
unsigned trigger;
|
||||||
char **pargv = NULL;
|
char **pargv;
|
||||||
int min_arg = 0;
|
int min_arg = 0;
|
||||||
int max_arg = -1;
|
int max_arg = -1;
|
||||||
|
|
||||||
#define SHOW_USAGE_IF_ERROR 1
|
#define SHOW_USAGE_IF_ERROR 1
|
||||||
#define ALL_ARGV_IS_OPTS 2
|
#define ALL_ARGV_IS_OPTS 2
|
||||||
#define FIRST_ARGV_IS_OPT 4
|
#define FIRST_ARGV_IS_OPT 4
|
||||||
#define FREE_FIRST_ARGV_IS_OPT (8 * !DONT_USE_PRINTF)
|
|
||||||
|
|
||||||
int spec_flgs = 0;
|
int spec_flgs = 0;
|
||||||
|
|
||||||
@ -493,17 +488,18 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
}
|
}
|
||||||
va_end(p);
|
va_end(p);
|
||||||
|
|
||||||
if (spec_flgs & FIRST_ARGV_IS_OPT) {
|
if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) {
|
||||||
if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {
|
pargv = argv + 1;
|
||||||
#if DONT_USE_PRINTF
|
while (*pargv) {
|
||||||
char *pp = alloca(strlen(argv[1]) + 2);
|
if (pargv[0][0] != '-' && pargv[0][0] != '\0') {
|
||||||
*pp = '-';
|
char *pp = alloca(strlen(*pargv) + 2);
|
||||||
strcpy(pp + 1, argv[1]);
|
*pp = '-';
|
||||||
argv[1] = pp;
|
strcpy(pp + 1, *pargv);
|
||||||
#else
|
*pargv = pp;
|
||||||
argv[1] = xasprintf("-%s", argv[1]);
|
}
|
||||||
spec_flgs |= FREE_FIRST_ARGV_IS_OPT;
|
if (!(spec_flgs & ALL_ARGV_IS_OPTS))
|
||||||
#endif
|
break;
|
||||||
|
pargv++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +525,7 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
/* optreset = 1; */
|
/* optreset = 1; */
|
||||||
#endif
|
#endif
|
||||||
/* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
|
/* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
|
||||||
|
pargv = NULL;
|
||||||
|
|
||||||
/* Note: just "getopt() <= 0" will not work well for
|
/* Note: just "getopt() <= 0" will not work well for
|
||||||
* "fake" short options, like this one:
|
* "fake" short options, like this one:
|
||||||
@ -540,12 +537,17 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
#else
|
#else
|
||||||
while ((c = getopt(argc, argv, applet_opts)) != -1) {
|
while ((c = getopt(argc, argv, applet_opts)) != -1) {
|
||||||
#endif
|
#endif
|
||||||
|
/* getopt prints "option requires an argument -- X"
|
||||||
|
* and returns '?' if an option has no arg, but one is reqd */
|
||||||
c &= 0xff; /* fight libc's sign extension */
|
c &= 0xff; /* fight libc's sign extension */
|
||||||
loop_arg_is_opt:
|
|
||||||
for (on_off = complementary; on_off->opt_char != c; on_off++) {
|
for (on_off = complementary; on_off->opt_char != c; on_off++) {
|
||||||
/* c==0 if long opt have non NULL flag */
|
/* c can be NUL if long opt has non-NULL ->flag,
|
||||||
if (on_off->opt_char == '\0' && c != '\0')
|
* but we construct long opts so that flag
|
||||||
|
* is always NULL (see above) */
|
||||||
|
if (on_off->opt_char == '\0' /* && c != '\0' */) {
|
||||||
|
/* c is probably '?' - "bad option" */
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flags & on_off->incongruously)
|
if (flags & on_off->incongruously)
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
@ -570,24 +572,6 @@ getopt32(char **argv, const char *applet_opts, ...)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spec_flgs & ALL_ARGV_IS_OPTS) {
|
|
||||||
/* process argv is option, for example "ps" applet */
|
|
||||||
if (pargv == NULL)
|
|
||||||
pargv = argv + optind;
|
|
||||||
while (*pargv) {
|
|
||||||
c = **pargv;
|
|
||||||
if (c == '\0') {
|
|
||||||
pargv++;
|
|
||||||
} else {
|
|
||||||
(*pargv)++;
|
|
||||||
goto loop_arg_is_opt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spec_flgs & FREE_FIRST_ARGV_IS_OPT)
|
|
||||||
free(argv[1]);
|
|
||||||
|
|
||||||
/* check depending requires for given options */
|
/* check depending requires for given options */
|
||||||
for (on_off = complementary; on_off->opt_char; on_off++) {
|
for (on_off = complementary; on_off->opt_char; on_off++) {
|
||||||
if (on_off->requires && (flags & on_off->switch_on) &&
|
if (on_off->requires && (flags & on_off->switch_on) &&
|
||||||
|
@ -763,8 +763,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
/* all args are options; -n NUM */
|
/* all args are options; -n NUM */
|
||||||
opt_complementary = "-:n+";
|
opt_complementary = "-:n+";
|
||||||
getopt32(argv, "d:n:b", &sinterval, &iterations);
|
if (getopt32(argv, "d:n:b", &sinterval, &iterations) & OPT_d) {
|
||||||
if (option_mask32 & OPT_d) {
|
|
||||||
/* Need to limit it to not overflow poll timeout */
|
/* Need to limit it to not overflow poll timeout */
|
||||||
interval = xatou16(sinterval); // -d
|
interval = xatou16(sinterval); // -d
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user