summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormillert <>2013-06-08 22:47:56 +0000
committermillert <>2013-06-08 22:47:56 +0000
commit2db43f90de87aaaadeccbb6ce07a69308fcecdf4 (patch)
treef0f260dbfc722b6b1bcbc5a3397b2da4124b83ea /src
parent93ea33ae58b1293bd129bc91689dc622e69810df (diff)
downloadopenbsd-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.c37
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 */
77static int getopt_internal(int, char * const *, const char *, 77static int getopt_internal(int, char * const *, const char *,
78 const struct option *, int *, int); 78 const struct option *, int *, int);
79static int parse_long_options(char * const *, const char *, 79static int parse_long_options(char * const *, const char *,
80 const struct option *, int *, int); 80 const struct option *, int *, int, int);
81static int gcd(int, int); 81static int gcd(int, int);
82static void permute_args(int, int, int, char * const *); 82static 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 */
158static int 158static int
159parse_long_options(char * const *nargv, const char *options, 159parse_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 }