aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 16:46:17 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-08-04 16:46:17 +0200
commitdd5a40246b91bd5d3d165998e6ac3cc4f7083f63 (patch)
treeffbd1f118040b36ae23f43d491bd8de097fd0843
parent727948e585cb133c32c8d42570e5524c58190307 (diff)
downloadbusybox-dd5a40246b91bd5d3d165998e6ac3cc4f7083f63.tar.gz
getopt32: move support for "always treat first arg as option" to users (tar/ar)
Now getopt() never leaks (and never performs) any xmalloc's. function old new delta ar_main 522 556 +34 tar_main 986 1014 +28 getopt32 1458 1350 -108 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 62/-108) Total: -46 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/ar.c6
-rw-r--r--archival/tar.c4
-rw-r--r--libbb/getopt32.c36
3 files changed, 10 insertions, 36 deletions
diff --git a/archival/ar.c b/archival/ar.c
index 2886d155b..46c10aad4 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -240,10 +240,12 @@ int ar_main(int argc UNUSED_PARAM, char **argv)
archive_handle = init_handle();
- /* --: prepend '-' to the first argument if required */
+ /* prepend '-' to the first argument if required */
+ if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0')
+ argv[1] = xasprintf("-%s", argv[1]);
/* -1: at least one param is reqd */
/* one of p,t,x[,r] is required */
- opt_complementary = "--:-1:p:t:x"IF_FEATURE_AR_CREATE(":r");
+ opt_complementary = "-1:p:t:x"IF_FEATURE_AR_CREATE(":r");
opt = getopt32(argv, "voc""ptx"IF_FEATURE_AR_CREATE("r"));
argv += optind;
diff --git a/archival/tar.c b/archival/tar.c
index 280ded4e1..f62b33005 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -966,7 +966,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
/* Prepend '-' to the first argument if required */
- opt_complementary = "--:" // first arg is options
+ if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0')
+ argv[1] = xasprintf("-%s", argv[1]);
+ opt_complementary =
"tt:vv:" // count -t,-v
#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
"\xff::" // --exclude=PATTERN is a list
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 129840cea..513415894 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -171,16 +171,6 @@ const char *opt_complementary
Special characters:
- "--" 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
- such as "ar" and "tar":
- tar xvf foo.tar
-
- 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.
-
"-N" A dash as the first char in a opt_complementary group followed
by a single digit (0-9) means that at least N non-option
arguments must be present on the command line
@@ -337,6 +327,8 @@ const char *applet_long_options;
uint32_t option_mask32;
+/* Please keep getopt32 free from xmalloc */
+
uint32_t FAST_FUNC
getopt32(char **argv, const char *applet_opts, ...)
{
@@ -354,12 +346,10 @@ getopt32(char **argv, const char *applet_opts, ...)
struct option *long_options = (struct option *) &bb_null_long_options;
#endif
unsigned trigger;
- char **pargv;
int min_arg = 0;
int max_arg = -1;
#define SHOW_USAGE_IF_ERROR 1
-#define FIRST_ARGV_IS_OPT 2
int spec_flgs = 0;
@@ -467,12 +457,7 @@ getopt32(char **argv, const char *applet_opts, ...)
continue;
}
if (*s == '-') {
- if (c < '0' || c > '9') {
- if (c == '-') {
- spec_flgs |= FIRST_ARGV_IS_OPT;
- s++;
- }
- } else {
+ if (c >= '0' && c <= '9') {
min_arg = c - '0';
s++;
}
@@ -535,21 +520,6 @@ getopt32(char **argv, const char *applet_opts, ...)
opt_complementary = NULL;
va_end(p);
- if (spec_flgs & FIRST_ARGV_IS_OPT) {
- pargv = argv + 1;
- if (*pargv) {
- if (pargv[0][0] != '-' && pargv[0][0] != '\0') {
- /* Can't use alloca: opts with params will
- * return pointers to stack!
- * NB: we leak these allocations... */
- char *pp = xmalloc(strlen(*pargv) + 2);
- *pp = '-';
- strcpy(pp + 1, *pargv);
- *pargv = pp;
- }
- }
- }
-
/* In case getopt32 was already called:
* reset the libc getopt() function, which keeps internal state.
* run_nofork_applet() does this, but we might end up here