diff options
Diffstat (limited to 'src/lib/libc')
| -rw-r--r-- | src/lib/libc/stdlib/getopt_long.c | 429 |
1 files changed, 208 insertions, 221 deletions
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index 4fc1874367..130c1d8bfa 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.2 2002/12/03 20:28:12 millert Exp $ */ | 1 | /* $OpenBSD: getopt_long.c,v 1.3 2002/12/05 21:45:01 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 | /*- |
| @@ -38,7 +38,7 @@ | |||
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | #if defined(LIBC_SCCS) && !defined(lint) | 40 | #if defined(LIBC_SCCS) && !defined(lint) |
| 41 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.2 2002/12/03 20:28:12 millert Exp $"; | 41 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.3 2002/12/05 21:45:01 millert Exp $"; |
| 42 | #endif /* LIBC_SCCS and not lint */ | 42 | #endif /* LIBC_SCCS and not lint */ |
| 43 | 43 | ||
| 44 | #include <err.h> | 44 | #include <err.h> |
| @@ -57,9 +57,9 @@ char *optarg; /* argument associated with option */ | |||
| 57 | 57 | ||
| 58 | #define PRINT_ERROR ((opterr) && (*options != ':')) | 58 | #define PRINT_ERROR ((opterr) && (*options != ':')) |
| 59 | 59 | ||
| 60 | #define FLAG_PERMUTE 0x01 | 60 | #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ |
| 61 | #define FLAG_ALLARGS 0x02 | 61 | #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ |
| 62 | #define FLAG_LONGONLY 0x04 | 62 | #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ |
| 63 | 63 | ||
| 64 | /* return values */ | 64 | /* return values */ |
| 65 | #define BADCH (int)'?' | 65 | #define BADCH (int)'?' |
| @@ -68,9 +68,10 @@ char *optarg; /* argument associated with option */ | |||
| 68 | 68 | ||
| 69 | #define EMSG "" | 69 | #define EMSG "" |
| 70 | 70 | ||
| 71 | static int getopt_internal(int, char * const *, const char *, int); | 71 | static int getopt_internal(int, char * const *, const char *, |
| 72 | static int getopt_long_internal(int, char * const *, const char *, | 72 | const struct option *, int *, int); |
| 73 | const struct option *, int *, int); | 73 | static int parse_long_options(int, char * const *, const char *, |
| 74 | const struct option *, int *, int); | ||
| 74 | static int gcd(int, int); | 75 | static int gcd(int, int); |
| 75 | static void permute_args(int, int, int, char * const *); | 76 | static void permute_args(int, int, int, char * const *); |
| 76 | 77 | ||
| @@ -92,9 +93,7 @@ static const char illoptstring[] = "unknown option -- %s"; | |||
| 92 | * Compute the greatest common divisor of a and b. | 93 | * Compute the greatest common divisor of a and b. |
| 93 | */ | 94 | */ |
| 94 | static int | 95 | static int |
| 95 | gcd(a, b) | 96 | gcd(int a, int b) |
| 96 | int a; | ||
| 97 | int b; | ||
| 98 | { | 97 | { |
| 99 | int c; | 98 | int c; |
| 100 | 99 | ||
| @@ -105,7 +104,7 @@ gcd(a, b) | |||
| 105 | c = a % b; | 104 | c = a % b; |
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | return b; | 107 | return (b); |
| 109 | } | 108 | } |
| 110 | 109 | ||
| 111 | /* | 110 | /* |
| @@ -114,11 +113,8 @@ gcd(a, b) | |||
| 114 | * in each block). | 113 | * in each block). |
| 115 | */ | 114 | */ |
| 116 | static void | 115 | static void |
| 117 | permute_args(panonopt_start, panonopt_end, opt_end, nargv) | 116 | permute_args(int panonopt_start, int panonopt_end, int opt_end, |
| 118 | int panonopt_start; | 117 | char * const *nargv) |
| 119 | int panonopt_end; | ||
| 120 | int opt_end; | ||
| 121 | char * const *nargv; | ||
| 122 | { | 118 | { |
| 123 | int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; | 119 | int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
| 124 | char *swap; | 120 | char *swap; |
| @@ -149,23 +145,154 @@ permute_args(panonopt_start, panonopt_end, opt_end, nargv) | |||
| 149 | } | 145 | } |
| 150 | 146 | ||
| 151 | /* | 147 | /* |
| 148 | * parse_long_options -- | ||
| 149 | * Parse long options in argc/argv argument vector. | ||
| 150 | * Returns -2 if long_only is set and the current option could be a short | ||
| 151 | * (single character) option instead. | ||
| 152 | */ | ||
| 153 | static int | ||
| 154 | parse_long_options(int nargc, char * const *nargv, const char *options, | ||
| 155 | const struct option *long_options, int *idx, int long_only) | ||
| 156 | { | ||
| 157 | char *current_argv, *has_equal; | ||
| 158 | size_t current_argv_len; | ||
| 159 | int i, match; | ||
| 160 | |||
| 161 | current_argv = place; | ||
| 162 | match = -1; | ||
| 163 | |||
| 164 | optind++; | ||
| 165 | |||
| 166 | if ((has_equal = strchr(current_argv, '=')) != NULL) { | ||
| 167 | /* argument found (--option=arg) */ | ||
| 168 | current_argv_len = has_equal - current_argv; | ||
| 169 | has_equal++; | ||
| 170 | } else | ||
| 171 | current_argv_len = strlen(current_argv); | ||
| 172 | |||
| 173 | for (i = 0; long_options[i].name; i++) { | ||
| 174 | /* find matching long option */ | ||
| 175 | if (strncmp(current_argv, long_options[i].name, | ||
| 176 | current_argv_len)) | ||
| 177 | continue; | ||
| 178 | |||
| 179 | if (strlen(long_options[i].name) == current_argv_len) { | ||
| 180 | /* exact match */ | ||
| 181 | match = i; | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | /* | ||
| 185 | * Don't try a partial match of a short option when in | ||
| 186 | * long_only mode. Otherwise there is a potential conflict | ||
| 187 | * between partial matches and short options. | ||
| 188 | */ | ||
| 189 | if (long_only && current_argv_len == 1) | ||
| 190 | continue; | ||
| 191 | |||
| 192 | if (match == -1) /* partial match */ | ||
| 193 | match = i; | ||
| 194 | else { | ||
| 195 | /* ambiguous abbreviation */ | ||
| 196 | if (PRINT_ERROR) | ||
| 197 | warnx(ambig, (int)current_argv_len, | ||
| 198 | current_argv); | ||
| 199 | optopt = 0; | ||
| 200 | return (BADCH); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | if (match != -1) { /* option found */ | ||
| 204 | if (long_options[match].has_arg == no_argument | ||
| 205 | && has_equal) { | ||
| 206 | if (PRINT_ERROR) | ||
| 207 | warnx(noarg, (int)current_argv_len, | ||
| 208 | current_argv); | ||
| 209 | /* | ||
| 210 | * XXX: GNU sets optopt to val regardless of flag | ||
| 211 | */ | ||
| 212 | if (long_options[match].flag == NULL) | ||
| 213 | optopt = long_options[match].val; | ||
| 214 | else | ||
| 215 | optopt = 0; | ||
| 216 | return (BADARG); | ||
| 217 | } | ||
| 218 | if (long_options[match].has_arg == required_argument || | ||
| 219 | long_options[match].has_arg == optional_argument) { | ||
| 220 | if (has_equal) | ||
| 221 | optarg = has_equal; | ||
| 222 | else if (long_options[match].has_arg == | ||
| 223 | required_argument) { | ||
| 224 | /* | ||
| 225 | * optional argument doesn't use next nargv | ||
| 226 | */ | ||
| 227 | optarg = nargv[optind++]; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | if ((long_options[match].has_arg == required_argument) | ||
| 231 | && (optarg == NULL)) { | ||
| 232 | /* | ||
| 233 | * Missing argument; leading ':' indicates no error | ||
| 234 | * should be generated. | ||
| 235 | */ | ||
| 236 | if (PRINT_ERROR) | ||
| 237 | warnx(recargstring, | ||
| 238 | current_argv); | ||
| 239 | /* | ||
| 240 | * XXX: GNU sets optopt to val regardless of flag | ||
| 241 | */ | ||
| 242 | if (long_options[match].flag == NULL) | ||
| 243 | optopt = long_options[match].val; | ||
| 244 | else | ||
| 245 | optopt = 0; | ||
| 246 | --optind; | ||
| 247 | return (BADARG); | ||
| 248 | } | ||
| 249 | } else { /* unknown option */ | ||
| 250 | if (long_only) { | ||
| 251 | --optind; | ||
| 252 | return (-2); | ||
| 253 | } | ||
| 254 | if (PRINT_ERROR) | ||
| 255 | warnx(illoptstring, current_argv); | ||
| 256 | optopt = 0; | ||
| 257 | return (BADCH); | ||
| 258 | } | ||
| 259 | if (idx) | ||
| 260 | *idx = match; | ||
| 261 | if (long_options[match].flag) { | ||
| 262 | *long_options[match].flag = long_options[match].val; | ||
| 263 | return (0); | ||
| 264 | } else | ||
| 265 | return (long_options[match].val); | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 152 | * getopt_internal -- | 269 | * getopt_internal -- |
| 153 | * Parse argc/argv argument vector. Called by user level routines. | 270 | * Parse argc/argv argument vector. Called by user level routines. |
| 154 | * Returns -2 if -- is found (can be long option or end of options marker). | ||
| 155 | */ | 271 | */ |
| 156 | static int | 272 | static int |
| 157 | getopt_internal(nargc, nargv, options, flags) | 273 | getopt_internal(int nargc, char * const *nargv, const char *options, |
| 158 | int nargc; | 274 | const struct option *long_options, int *idx, int flags) |
| 159 | char * const *nargv; | ||
| 160 | const char *options; | ||
| 161 | int flags; | ||
| 162 | { | 275 | { |
| 163 | char *oli; /* option letter list index */ | 276 | char *oli; /* option letter list index */ |
| 164 | int optchar; | 277 | int optchar; |
| 278 | static int posixly_correct = -1; | ||
| 165 | 279 | ||
| 166 | optarg = NULL; | 280 | optarg = NULL; |
| 167 | 281 | ||
| 168 | /* | 282 | /* |
| 283 | * Disable GNU extensions if POSIXLY_CORRECT is set or options | ||
| 284 | * string begins with a '+'. | ||
| 285 | */ | ||
| 286 | if (posixly_correct == -1) | ||
| 287 | posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); | ||
| 288 | if (posixly_correct || *options == '+') | ||
| 289 | flags &= ~FLAG_PERMUTE; | ||
| 290 | else if (*options == '-') | ||
| 291 | flags |= FLAG_ALLARGS; | ||
| 292 | if (*options == '+' || *options == '-') | ||
| 293 | options++; | ||
| 294 | |||
| 295 | /* | ||
| 169 | * XXX Some programs (like rsyncd) expect to be able to | 296 | * XXX Some programs (like rsyncd) expect to be able to |
| 170 | * XXX re-initialize optind to 0 and have getopt_long(3) | 297 | * XXX re-initialize optind to 0 and have getopt_long(3) |
| 171 | * XXX properly function again. Work around this braindamage. | 298 | * XXX properly function again. Work around this braindamage. |
| @@ -194,7 +321,7 @@ start: | |||
| 194 | optind = nonopt_start; | 321 | optind = nonopt_start; |
| 195 | } | 322 | } |
| 196 | nonopt_start = nonopt_end = -1; | 323 | nonopt_start = nonopt_end = -1; |
| 197 | return -1; | 324 | return (-1); |
| 198 | } | 325 | } |
| 199 | if ((*(place = nargv[optind]) != '-') | 326 | if ((*(place = nargv[optind]) != '-') |
| 200 | || (place[1] == '\0')) { /* found non-option */ | 327 | || (place[1] == '\0')) { /* found non-option */ |
| @@ -205,14 +332,14 @@ start: | |||
| 205 | * return non-option as argument to option 1 | 332 | * return non-option as argument to option 1 |
| 206 | */ | 333 | */ |
| 207 | optarg = nargv[optind++]; | 334 | optarg = nargv[optind++]; |
| 208 | return INORDER; | 335 | return (INORDER); |
| 209 | } | 336 | } |
| 210 | if (!(flags & FLAG_PERMUTE)) { | 337 | if (!(flags & FLAG_PERMUTE)) { |
| 211 | /* | 338 | /* |
| 212 | * If no permutation wanted, stop parsing | 339 | * If no permutation wanted, stop parsing |
| 213 | * at first non-option. | 340 | * at first non-option. |
| 214 | */ | 341 | */ |
| 215 | return -1; | 342 | return (-1); |
| 216 | } | 343 | } |
| 217 | /* do permutation */ | 344 | /* do permutation */ |
| 218 | if (nonopt_start == -1) | 345 | if (nonopt_start == -1) |
| @@ -230,42 +357,64 @@ start: | |||
| 230 | } | 357 | } |
| 231 | if (nonopt_start != -1 && nonopt_end == -1) | 358 | if (nonopt_start != -1 && nonopt_end == -1) |
| 232 | nonopt_end = optind; | 359 | nonopt_end = optind; |
| 233 | if (place[1] && *++place == '-') { /* found "--" */ | 360 | if (strcmp(place, "--") == 0) { |
| 234 | place++; | 361 | optind++; |
| 235 | return -2; | 362 | place = EMSG; |
| 363 | /* | ||
| 364 | * We found an option (--), so if we skipped | ||
| 365 | * non-options, we have to permute. | ||
| 366 | */ | ||
| 367 | if (nonopt_end != -1) { | ||
| 368 | permute_args(nonopt_start, nonopt_end, | ||
| 369 | optind, nargv); | ||
| 370 | optind -= nonopt_end - nonopt_start; | ||
| 371 | } | ||
| 372 | nonopt_start = nonopt_end = -1; | ||
| 373 | return (-1); | ||
| 374 | } | ||
| 375 | place++; | ||
| 376 | |||
| 377 | /* Check long options if we have any */ | ||
| 378 | if (long_options != NULL) { | ||
| 379 | int long_only = 0; | ||
| 380 | |||
| 381 | if (*place == '-' || | ||
| 382 | (long_only = (flags & FLAG_LONGONLY))) { | ||
| 383 | if (!long_only) | ||
| 384 | place++; | ||
| 385 | optchar = parse_long_options(nargc, nargv, | ||
| 386 | options, long_options, idx, long_only); | ||
| 387 | if (optchar != -2) { | ||
| 388 | place = EMSG; | ||
| 389 | return (optchar); | ||
| 390 | } | ||
| 391 | } | ||
| 236 | } | 392 | } |
| 237 | } | 393 | } |
| 238 | if ((optchar = (int)*place++) == (int)':' || | 394 | if ((optchar = (int)*place++) == (int)':' || |
| 239 | (oli = strchr(options, optchar)) == NULL) { | 395 | (oli = strchr(options, optchar)) == NULL) { |
| 240 | /* could it be a long option with a single '-'? */ | ||
| 241 | if (flags & FLAG_LONGONLY) | ||
| 242 | return -2; | ||
| 243 | /* option letter unknown or ':' */ | 396 | /* option letter unknown or ':' */ |
| 244 | if (!*place) | 397 | if (!*place) |
| 245 | ++optind; | 398 | ++optind; |
| 246 | if (PRINT_ERROR) | 399 | if (PRINT_ERROR) |
| 247 | warnx(illoptchar, optchar); | 400 | warnx(illoptchar, optchar); |
| 248 | optopt = optchar; | 401 | optopt = optchar; |
| 249 | return BADCH; | 402 | return (BADCH); |
| 250 | } | 403 | } |
| 251 | if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ | 404 | if (long_options != NULL && optchar == 'W' && oli[1] == ';') { |
| 252 | /* XXX: what if no long options provided (called by getopt)? */ | 405 | /* -W long-option */ |
| 253 | if (*place) | ||
| 254 | return -2; | ||
| 255 | |||
| 256 | if (++optind >= nargc) { /* no arg */ | 406 | if (++optind >= nargc) { /* no arg */ |
| 257 | place = EMSG; | 407 | place = EMSG; |
| 258 | if (PRINT_ERROR) | 408 | if (PRINT_ERROR) |
| 259 | warnx(recargchar, optchar); | 409 | warnx(recargchar, optchar); |
| 260 | optopt = optchar; | 410 | optopt = optchar; |
| 261 | return BADARG; | 411 | return (BADARG); |
| 262 | } else /* white space */ | 412 | } else /* white space */ |
| 263 | place = nargv[optind]; | 413 | place = nargv[optind]; |
| 264 | /* | 414 | optchar = parse_long_options(nargc, nargv, options, |
| 265 | * Handle -W arg the same as --arg (which causes getopt to | 415 | long_options, idx, 0); |
| 266 | * stop parsing). | 416 | place = EMSG; |
| 267 | */ | 417 | return (optchar); |
| 268 | return -2; | ||
| 269 | } | 418 | } |
| 270 | if (*++oli != ':') { /* doesn't take argument */ | 419 | if (*++oli != ':') { /* doesn't take argument */ |
| 271 | if (!*place) | 420 | if (!*place) |
| @@ -281,7 +430,7 @@ start: | |||
| 281 | if (PRINT_ERROR) | 430 | if (PRINT_ERROR) |
| 282 | warnx(recargchar, optchar); | 431 | warnx(recargchar, optchar); |
| 283 | optopt = optchar; | 432 | optopt = optchar; |
| 284 | return BADARG; | 433 | return (BADARG); |
| 285 | } else | 434 | } else |
| 286 | optarg = nargv[optind]; | 435 | optarg = nargv[optind]; |
| 287 | } | 436 | } |
| @@ -289,7 +438,7 @@ start: | |||
| 289 | ++optind; | 438 | ++optind; |
| 290 | } | 439 | } |
| 291 | /* dump back option letter */ | 440 | /* dump back option letter */ |
| 292 | return optchar; | 441 | return (optchar); |
| 293 | } | 442 | } |
| 294 | 443 | ||
| 295 | #ifdef REPLACE_GETOPT | 444 | #ifdef REPLACE_GETOPT |
| @@ -300,183 +449,20 @@ start: | |||
| 300 | * [eventually this will replace the BSD getopt] | 449 | * [eventually this will replace the BSD getopt] |
| 301 | */ | 450 | */ |
| 302 | int | 451 | int |
| 303 | getopt(nargc, nargv, options) | 452 | getopt(int nargc, char * const *nargv, const char *options) |
| 304 | int nargc; | ||
| 305 | char * const *nargv; | ||
| 306 | const char *options; | ||
| 307 | { | 453 | { |
| 308 | int retval; | ||
| 309 | |||
| 310 | if ((retval = getopt_internal(nargc, nargv, options, 0)) == -2) { | ||
| 311 | ++optind; | ||
| 312 | /* | ||
| 313 | * We found an option (--), so if we skipped non-options, | ||
| 314 | * we have to permute. | ||
| 315 | */ | ||
| 316 | if (nonopt_end != -1) { | ||
| 317 | permute_args(nonopt_start, nonopt_end, optind, | ||
| 318 | nargv); | ||
| 319 | optind -= nonopt_end - nonopt_start; | ||
| 320 | } | ||
| 321 | nonopt_start = nonopt_end = -1; | ||
| 322 | retval = -1; | ||
| 323 | } | ||
| 324 | return retval; | ||
| 325 | } | ||
| 326 | #endif /* REPLACE_GETOPT */ | ||
| 327 | |||
| 328 | /* | ||
| 329 | * getopt_long_internal -- | ||
| 330 | * Parse argc/argv argument vector. | ||
| 331 | */ | ||
| 332 | static int | ||
| 333 | getopt_long_internal(nargc, nargv, options, long_options, idx, flags) | ||
| 334 | int nargc; | ||
| 335 | char * const *nargv; | ||
| 336 | const char *options; | ||
| 337 | const struct option *long_options; | ||
| 338 | int *idx; | ||
| 339 | int flags; | ||
| 340 | { | ||
| 341 | int retval; | ||
| 342 | 454 | ||
| 343 | /* | 455 | /* |
| 344 | * Disable GNU extensions if POSIXLY_CORRECT is set or options | 456 | * We dont' pass FLAG_PERMUTE to getopt_internal() since |
| 345 | * string begins with a '+'. | 457 | * the BSD getopt(3) (unlike GNU) has never done this. |
| 458 | * | ||
| 459 | * Furthermore, since many privileged programs call getopt() | ||
| 460 | * before dropping privileges it makes sense to keep things | ||
| 461 | * as simple (and bug-free) as possible. | ||
| 346 | */ | 462 | */ |
| 347 | if (getenv("POSIXLY_CORRECT")) { | 463 | return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); |
| 348 | if (*options == '+' || *options == '-') | ||
| 349 | options++; | ||
| 350 | } else { | ||
| 351 | if (*options == '+') { | ||
| 352 | options++; | ||
| 353 | } else { | ||
| 354 | flags |= FLAG_PERMUTE; | ||
| 355 | if (*options == '-') { | ||
| 356 | flags |= FLAG_ALLARGS; | ||
| 357 | options++; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | if ((retval = getopt_internal(nargc, nargv, options, flags)) == -2) { | ||
| 363 | char *current_argv, *has_equal; | ||
| 364 | size_t current_argv_len; | ||
| 365 | int i, match; | ||
| 366 | |||
| 367 | current_argv = place; | ||
| 368 | match = -1; | ||
| 369 | |||
| 370 | optind++; | ||
| 371 | place = EMSG; | ||
| 372 | |||
| 373 | if (*current_argv == '\0') { /* found "--" */ | ||
| 374 | /* | ||
| 375 | * We found an option (--), so if we skipped | ||
| 376 | * non-options, we have to permute. | ||
| 377 | */ | ||
| 378 | if (nonopt_end != -1) { | ||
| 379 | permute_args(nonopt_start, nonopt_end, | ||
| 380 | optind, nargv); | ||
| 381 | optind -= nonopt_end - nonopt_start; | ||
| 382 | } | ||
| 383 | nonopt_start = nonopt_end = -1; | ||
| 384 | return -1; | ||
| 385 | } | ||
| 386 | if ((has_equal = strchr(current_argv, '=')) != NULL) { | ||
| 387 | /* argument found (--option=arg) */ | ||
| 388 | current_argv_len = has_equal - current_argv; | ||
| 389 | has_equal++; | ||
| 390 | } else | ||
| 391 | current_argv_len = strlen(current_argv); | ||
| 392 | |||
| 393 | for (i = 0; long_options[i].name; i++) { | ||
| 394 | /* find matching long option */ | ||
| 395 | if (strncmp(current_argv, long_options[i].name, | ||
| 396 | current_argv_len)) | ||
| 397 | continue; | ||
| 398 | |||
| 399 | if (strlen(long_options[i].name) == | ||
| 400 | (unsigned)current_argv_len) { | ||
| 401 | /* exact match */ | ||
| 402 | match = i; | ||
| 403 | break; | ||
| 404 | } | ||
| 405 | if (match == -1) /* partial match */ | ||
| 406 | match = i; | ||
| 407 | else { | ||
| 408 | /* ambiguous abbreviation */ | ||
| 409 | if (PRINT_ERROR) | ||
| 410 | warnx(ambig, (int)current_argv_len, | ||
| 411 | current_argv); | ||
| 412 | optopt = 0; | ||
| 413 | return BADCH; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | if (match != -1) { /* option found */ | ||
| 417 | if (long_options[match].has_arg == no_argument | ||
| 418 | && has_equal) { | ||
| 419 | if (PRINT_ERROR) | ||
| 420 | warnx(noarg, (int)current_argv_len, | ||
| 421 | current_argv); | ||
| 422 | /* | ||
| 423 | * XXX: GNU sets optopt to val regardless of | ||
| 424 | * flag | ||
| 425 | */ | ||
| 426 | if (long_options[match].flag == NULL) | ||
| 427 | optopt = long_options[match].val; | ||
| 428 | else | ||
| 429 | optopt = 0; | ||
| 430 | return BADARG; | ||
| 431 | } | ||
| 432 | if (long_options[match].has_arg == required_argument || | ||
| 433 | long_options[match].has_arg == optional_argument) { | ||
| 434 | if (has_equal) | ||
| 435 | optarg = has_equal; | ||
| 436 | else if (long_options[match].has_arg == | ||
| 437 | required_argument) { | ||
| 438 | /* | ||
| 439 | * optional argument doesn't use | ||
| 440 | * next nargv | ||
| 441 | */ | ||
| 442 | optarg = nargv[optind++]; | ||
| 443 | } | ||
| 444 | } | ||
| 445 | if ((long_options[match].has_arg == required_argument) | ||
| 446 | && (optarg == NULL)) { | ||
| 447 | /* | ||
| 448 | * Missing argument; leading ':' | ||
| 449 | * indicates no error should be generated | ||
| 450 | */ | ||
| 451 | if (PRINT_ERROR) | ||
| 452 | warnx(recargstring, current_argv); | ||
| 453 | /* | ||
| 454 | * XXX: GNU sets optopt to val regardless | ||
| 455 | * of flag | ||
| 456 | */ | ||
| 457 | if (long_options[match].flag == NULL) | ||
| 458 | optopt = long_options[match].val; | ||
| 459 | else | ||
| 460 | optopt = 0; | ||
| 461 | --optind; | ||
| 462 | return BADARG; | ||
| 463 | } | ||
| 464 | } else { /* unknown option */ | ||
| 465 | if (PRINT_ERROR) | ||
| 466 | warnx(illoptstring, current_argv); | ||
| 467 | optopt = 0; | ||
| 468 | return BADCH; | ||
| 469 | } | ||
| 470 | if (long_options[match].flag) { | ||
| 471 | *long_options[match].flag = long_options[match].val; | ||
| 472 | retval = 0; | ||
| 473 | } else | ||
| 474 | retval = long_options[match].val; | ||
| 475 | if (idx) | ||
| 476 | *idx = match; | ||
| 477 | } | ||
| 478 | return retval; | ||
| 479 | } | 464 | } |
| 465 | #endif /* REPLACE_GETOPT */ | ||
| 480 | 466 | ||
| 481 | /* | 467 | /* |
| 482 | * getopt_long -- | 468 | * getopt_long -- |
| @@ -491,7 +477,8 @@ getopt_long(nargc, nargv, options, long_options, idx) | |||
| 491 | int *idx; | 477 | int *idx; |
| 492 | { | 478 | { |
| 493 | 479 | ||
| 494 | return getopt_long_internal(nargc, nargv, options, long_options, idx, 0); | 480 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
| 481 | FLAG_PERMUTE)); | ||
| 495 | } | 482 | } |
| 496 | 483 | ||
| 497 | /* | 484 | /* |
| @@ -507,6 +494,6 @@ getopt_long_only(nargc, nargv, options, long_options, idx) | |||
| 507 | int *idx; | 494 | int *idx; |
| 508 | { | 495 | { |
| 509 | 496 | ||
| 510 | return getopt_long_internal(nargc, nargv, options, long_options, idx, | 497 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
| 511 | FLAG_LONGONLY); | 498 | FLAG_PERMUTE|FLAG_LONGONLY)); |
| 512 | } | 499 | } |
