getopt32: factor out code to treat all args as options
Working towards making getopt32() xmalloc-free
function old new delta
make_all_argv_opts - 58 +58
top_main 914 912 -2
getopt32 1517 1458 -59
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/2 up/down: 58/-61) Total: -3 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/include/libbb.h b/include/libbb.h
index 46180c5..bb27c59 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1183,7 +1183,9 @@
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()
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 458973f..73201a6 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -40,7 +40,6 @@
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
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 80f4cc0..129840c 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
strcpy(pp + 1, *pargv);
*pargv = pp;
}
- if (!(spec_flgs & ALL_ARGV_IS_OPTS))
- break;
- pargv++;
}
}
diff --git a/libbb/getopt_allopts.c b/libbb/getopt_allopts.c
new file mode 100644
index 0000000..a67d2b7
--- /dev/null
+++ b/libbb/getopt_allopts.c
@@ -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;
+ }
+}
diff --git a/procps/ps.c b/procps/ps.c
index eb1946d..081479b 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -715,7 +715,8 @@
# 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 @@
}
# 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
diff --git a/procps/top.c b/procps/top.c
index 015d1ab..1bc432f 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -1110,15 +1110,14 @@
#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 */