getopt32: factor out code to treat all args as options
No binary (build failed)
—
(log yok)
| @@ -1183,7 +1183,9 @@ extern const char *opt_complementary; | |
| extern const char *applet_long_options; | |
| #endif | |
| extern uint32_t option_mask32; | |
| - | extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; |
| + | uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; |
| + | /* For top, ps. Some argv[i] are replaced by malloced "-opt" strings */ |
| + | void make_all_argv_opts(char **argv) FAST_FUNC; |
| /* BSD-derived getopt() functions require that optind be set to 1 in | |
| * order to reset getopt() state. This used to be generally accepted | |
| * way of resetting getopt(). However, glibc's getopt() | |
| @@ -40,7 +40,6 @@ lib-y += full_write.o | |
| lib-y += get_console.o | |
| lib-y += get_last_path_component.o | |
| lib-y += get_line_from_file.o | |
| - | lib-y += getopt32.o |
| lib-y += getpty.o | |
| lib-y += get_volsize.o | |
| lib-y += herror_msg.o | |
| @@ -6,12 +6,13 @@ | |
| * | |
| * Licensed under GPLv2 or later, see file LICENSE in this source tree. | |
| */ | |
| - | |
| #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | |
| # include <getopt.h> | |
| #endif | |
| #include "libbb.h" | |
| + | //kbuild:lib-y += getopt32.o |
| + | |
| /* Documentation | |
| uint32_t | |
| @@ -170,21 +171,6 @@ const char *opt_complementary | |
| Special characters: | |
| - | "-" A group consisting of just a dash forces all arguments |
| - | to be treated as options, even if they have no leading dashes. |
| - | Next char in this case can't be a digit (0-9), use ':' or end of line. |
| - | Example: |
| - | |
| - | opt_complementary = "-:w-x:x-w"; // "-w-x:x-w" would also work, |
| - | getopt32(argv, "wx"); // but is less readable |
| - | |
| - | This makes it possible to use options without a dash (./program w x) |
| - | as well as with a dash (./program -x). |
| - | |
| - | NB: getopt32() will leak a small amount of memory if you use |
| - | this option! Do not use it if there is a possibility of recursive |
| - | getopt32() calls. |
| - | |
| "--" A double dash at the beginning of opt_complementary means the | |
| argv[1] string should always be treated as options, even if it isn't | |
| prefixed with a "-". This is useful for special syntax in applets | |
| @@ -373,8 +359,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| int max_arg = -1; | |
| #define SHOW_USAGE_IF_ERROR 1 | |
| - | #define ALL_ARGV_IS_OPTS 2 |
| - | #define FIRST_ARGV_IS_OPT 4 |
| + | #define FIRST_ARGV_IS_OPT 2 |
| int spec_flgs = 0; | |
| @@ -486,8 +471,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| if (c == '-') { | |
| spec_flgs |= FIRST_ARGV_IS_OPT; | |
| s++; | |
| - | } else |
| - | spec_flgs |= ALL_ARGV_IS_OPTS; |
| + | } |
| } else { | |
| min_arg = c - '0'; | |
| s++; | |
| @@ -551,9 +535,9 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| opt_complementary = NULL; | |
| va_end(p); | |
| - | if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) { |
| + | if (spec_flgs & FIRST_ARGV_IS_OPT) { |
| pargv = argv + 1; | |
| - | while (*pargv) { |
| + | if (*pargv) { |
| if (pargv[0][0] != '-' && pargv[0][0] != '\0') { | |
| /* Can't use alloca: opts with params will | |
| * return pointers to stack! | |
| @@ -563,9 +547,6 @@ getopt32(char **argv, const char *applet_opts, ...) | |
| strcpy(pp + 1, *pargv); | |
| *pargv = pp; | |
| } | |
| - | if (!(spec_flgs & ALL_ARGV_IS_OPTS)) |
| - | break; |
| - | pargv++; |
| } | |
| } | |
| @@ -0,0 +1,27 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Copyright (C) 2017 Denys Vlasenko |
| + | * |
| + | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| + | */ |
| + | #include "libbb.h" |
| + | |
| + | //kbuild:lib-y += getopt_allopts.o |
| + | |
| + | void FAST_FUNC make_all_argv_opts(char **argv) |
| + | { |
| + | /* Note: we skip argv[0] */ |
| + | while (*++argv) { |
| + | char *p; |
| + | |
| + | if (argv[0][0] == '-') |
| + | continue; |
| + | /* Neither top nor ps care if "" arg turns into "-" */ |
| + | /*if (argv[0][0] == '\0') |
| + | continue;*/ |
| + | p = xmalloc(strlen(*argv) + 2); |
| + | *p = '-'; |
| + | strcpy(p + 1, *argv); |
| + | *argv = p; |
| + | } |
| + | } |
| @@ -715,7 +715,8 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |
| # if ENABLE_FEATURE_PS_WIDE | |
| /* -w is a bit complicated */ | |
| int w_count = 0; | |
| - | opt_complementary = "-:ww"; |
| + | make_all_argv_opts(argv); |
| + | opt_complementary = "ww"; |
| opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l") | |
| "w", &w_count); | |
| /* if w is given once, GNU ps sets the width to 132, | |
| @@ -731,7 +732,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |
| } | |
| # else | |
| /* -w is not supported, only -Z and/or -T */ | |
| - | opt_complementary = "-"; |
| + | make_all_argv_opts(argv); |
| opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l")); | |
| # endif | |
| @@ -1110,15 +1110,14 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |
| #endif | |
| /* all args are options; -n NUM */ | |
| - | opt_complementary = "-"; /* options can be specified w/o dash */ |
| + | make_all_argv_opts(argv); /* options can be specified w/o dash */ |
| col = getopt32(argv, "d:n:b"IF_FEATURE_TOPMEM("m"), &str_interval, &str_iterations); | |
| #if ENABLE_FEATURE_TOPMEM | |
| if (col & OPT_m) /* -m (busybox specific) */ | |
| scan_mask = TOPMEM_MASK; | |
| #endif | |
| if (col & OPT_d) { | |
| - | /* work around for "-d 1" -> "-d -1" done by getopt32 |
| - | * (opt_complementary == "-" does this) */ |
| + | /* work around for "-d 1" -> "-d -1" done by make_all_argv_opts() */ |
| if (str_interval[0] == '-') | |
| str_interval++; | |
| /* Need to limit it to not overflow poll timeout */ | |