diff options
author | millert <> | 2013-06-08 22:47:56 +0000 |
---|---|---|
committer | millert <> | 2013-06-08 22:47:56 +0000 |
commit | 2db43f90de87aaaadeccbb6ce07a69308fcecdf4 (patch) | |
tree | f0f260dbfc722b6b1bcbc5a3397b2da4124b83ea /src | |
parent | 93ea33ae58b1293bd129bc91689dc622e69810df (diff) | |
download | openbsd-2db43f90de87aaaadeccbb6ce07a69308fcecdf4.tar.gz openbsd-2db43f90de87aaaadeccbb6ce07a69308fcecdf4.tar.bz2 openbsd-2db43f90de87aaaadeccbb6ce07a69308fcecdf4.zip |
Fix parsing of ambiguous options, the whole loop must be processed.
From FreeBSD. OK miod@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/getopt_long.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index e149fe0ace..f46cd8bf4e 100644 --- a/src/lib/libc/stdlib/getopt_long.c +++ b/src/lib/libc/stdlib/getopt_long.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $ */ | 1 | /* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */ |
2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ | 2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ |
3 | 3 | ||
4 | /* | 4 | /* |
@@ -77,7 +77,7 @@ char *optarg; /* argument associated with option */ | |||
77 | static int getopt_internal(int, char * const *, const char *, | 77 | static int getopt_internal(int, char * const *, const char *, |
78 | const struct option *, int *, int); | 78 | const struct option *, int *, int); |
79 | static int parse_long_options(char * const *, const char *, | 79 | static int parse_long_options(char * const *, const char *, |
80 | const struct option *, int *, int); | 80 | const struct option *, int *, int, int); |
81 | static int gcd(int, int); | 81 | static int gcd(int, int); |
82 | static void permute_args(int, int, int, char * const *); | 82 | static void permute_args(int, int, int, char * const *); |
83 | 83 | ||
@@ -157,14 +157,16 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, | |||
157 | */ | 157 | */ |
158 | static int | 158 | static int |
159 | parse_long_options(char * const *nargv, const char *options, | 159 | parse_long_options(char * const *nargv, const char *options, |
160 | const struct option *long_options, int *idx, int short_too) | 160 | const struct option *long_options, int *idx, int short_too, int flags) |
161 | { | 161 | { |
162 | char *current_argv, *has_equal; | 162 | char *current_argv, *has_equal; |
163 | size_t current_argv_len; | 163 | size_t current_argv_len; |
164 | int i, match; | 164 | int i, match, exact_match, second_partial_match; |
165 | 165 | ||
166 | current_argv = place; | 166 | current_argv = place; |
167 | match = -1; | 167 | match = -1; |
168 | exact_match = 0; | ||
169 | second_partial_match = 0; | ||
168 | 170 | ||
169 | optind++; | 171 | optind++; |
170 | 172 | ||
@@ -184,6 +186,7 @@ parse_long_options(char * const *nargv, const char *options, | |||
184 | if (strlen(long_options[i].name) == current_argv_len) { | 186 | if (strlen(long_options[i].name) == current_argv_len) { |
185 | /* exact match */ | 187 | /* exact match */ |
186 | match = i; | 188 | match = i; |
189 | exact_match = 1; | ||
187 | break; | 190 | break; |
188 | } | 191 | } |
189 | /* | 192 | /* |
@@ -193,16 +196,20 @@ parse_long_options(char * const *nargv, const char *options, | |||
193 | if (short_too && current_argv_len == 1) | 196 | if (short_too && current_argv_len == 1) |
194 | continue; | 197 | continue; |
195 | 198 | ||
196 | if (match == -1) /* partial match */ | 199 | if (match == -1) /* first partial match */ |
197 | match = i; | 200 | match = i; |
198 | else { | 201 | else if ((flags & FLAG_LONGONLY) || |
199 | /* ambiguous abbreviation */ | 202 | long_options[i].has_arg != long_options[match].has_arg || |
200 | if (PRINT_ERROR) | 203 | long_options[i].flag != long_options[match].flag || |
201 | warnx(ambig, (int)current_argv_len, | 204 | long_options[i].val != long_options[match].val) |
202 | current_argv); | 205 | second_partial_match = 1; |
203 | optopt = 0; | 206 | } |
204 | return (BADCH); | 207 | if (!exact_match && second_partial_match) { |
205 | } | 208 | /* ambiguous abbreviation */ |
209 | if (PRINT_ERROR) | ||
210 | warnx(ambig, (int)current_argv_len, current_argv); | ||
211 | optopt = 0; | ||
212 | return (BADCH); | ||
206 | } | 213 | } |
207 | if (match != -1) { /* option found */ | 214 | if (match != -1) { /* option found */ |
208 | if (long_options[match].has_arg == no_argument | 215 | if (long_options[match].has_arg == no_argument |
@@ -398,7 +405,7 @@ start: | |||
398 | short_too = 1; /* could be short option too */ | 405 | short_too = 1; /* could be short option too */ |
399 | 406 | ||
400 | optchar = parse_long_options(nargv, options, long_options, | 407 | optchar = parse_long_options(nargv, options, long_options, |
401 | idx, short_too); | 408 | idx, short_too, flags); |
402 | if (optchar != -1) { | 409 | if (optchar != -1) { |
403 | place = EMSG; | 410 | place = EMSG; |
404 | return (optchar); | 411 | return (optchar); |
@@ -435,7 +442,7 @@ start: | |||
435 | } else /* white space */ | 442 | } else /* white space */ |
436 | place = nargv[optind]; | 443 | place = nargv[optind]; |
437 | optchar = parse_long_options(nargv, options, long_options, | 444 | optchar = parse_long_options(nargv, options, long_options, |
438 | idx, 0); | 445 | idx, 0, flags); |
439 | place = EMSG; | 446 | place = EMSG; |
440 | return (optchar); | 447 | return (optchar); |
441 | } | 448 | } |