diff options
author | Rich Felker <dalias@aerifal.cx> | 2015-01-11 16:32:47 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2015-01-11 16:32:47 -0500 |
commit | 699d4532f6a8f792271c7f46608e2505ca3afc21 (patch) | |
tree | d22470164091885b9987df432e6c6527b07837cc /src/misc | |
parent | c574321d75f035ff6d2c18dfb7e3f70db60ba7bd (diff) | |
download | musl-699d4532f6a8f792271c7f46608e2505ca3afc21.tar.gz |
fix regression in getopt_long support for non-option arguments
commit b72cd07f176b876aa51864d93aa8101477b1d732 added support for a
this feature in getopt, but it was later broken in the case where
getopt_long is used as a side effect of the changes made in commit
91184c4f16b143107fa9935edebe5d2b20bd70d8, which prevented the
underlying getopt call from seeing the leading '-' or '+' character in
optstring.
this commit changes the logic in the getopt_long core to check for a
leading colon, possibly after the leading '-' or '+', without
depending on the latter having been skipped by the caller. a minor
incorrectness in the return value for one error condition in
getopt_long is also fixed when opterr has been set to zero but
optstring has no leading ':'.
Diffstat (limited to 'src/misc')
-rw-r--r-- | src/misc/getopt_long.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c index e5a4a75a..ffbcd423 100644 --- a/src/misc/getopt_long.c +++ b/src/misc/getopt_long.c @@ -23,7 +23,6 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) { int ret, skipped, resumed; - const char *optstring2 = optstring + 1; if (!optind || __optreset) { __optreset = 0; __optpos = 0; @@ -38,10 +37,9 @@ static int __getopt_long(int argc, char *const *argv, const char *optstring, con if (argv[i][0] == '-' && argv[i][1]) break; } optind = i; - optstring2 = optstring; } resumed = optind; - ret = __getopt_long_core(argc, argv, optstring2, longopts, idx, longonly); + ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); if (resumed > skipped) { int i, cnt = optind-resumed; for (i=0; i<cnt; i++) @@ -58,6 +56,7 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring ((longonly && argv[optind][1]) || (argv[optind][1] == '-' && argv[optind][2]))) { + int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; int i, cnt, match; char *opt; for (cnt=i=0; longopts[i].name; i++) { @@ -79,7 +78,7 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring optopt = longopts[i].val; if (*opt == '=') { if (!longopts[i].has_arg) { - if (optstring[0] == ':' || !opterr) + if (colon || !opterr) return '?'; __getopt_msg(argv[0], ": option does not take an argument: ", @@ -91,8 +90,8 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring } else { if (longopts[i].has_arg == required_argument) { if (!(optarg = argv[optind])) { - if (optstring[0] == ':' || !opterr) - return ':'; + if (colon) return ':'; + if (!opterr) return '?'; __getopt_msg(argv[0], ": option requires an argument: ", longopts[i].name, @@ -110,7 +109,7 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring return longopts[i].val; } if (argv[optind][1] == '-') { - if (optstring[0] != ':' && opterr) + if (!colon && opterr) __getopt_msg(argv[0], cnt ? ": option is ambiguous: " : ": unrecognized option: ", |