199a2dd95SBruce Richardson /* SPDX-License-Identifier: ISC AND BSD-2-Clause 299a2dd95SBruce Richardson * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> 399a2dd95SBruce Richardson * 499a2dd95SBruce Richardson * Sponsored in part by the Defense Advanced Research Projects 599a2dd95SBruce Richardson * Agency (DARPA) and Air Force Research Laboratory, Air Force 699a2dd95SBruce Richardson * Materiel Command, USAF, under agreement number F39502-99-1-0512. 799a2dd95SBruce Richardson */ 899a2dd95SBruce Richardson /* 999a2dd95SBruce Richardson * Copyright (c) 2000 The NetBSD Foundation, Inc. 1099a2dd95SBruce Richardson * All rights reserved. 1199a2dd95SBruce Richardson * 1299a2dd95SBruce Richardson * This code is derived from software contributed to The NetBSD Foundation 1399a2dd95SBruce Richardson * by Dieter Baron and Thomas Klausner. 1499a2dd95SBruce Richardson */ 1599a2dd95SBruce Richardson 1699a2dd95SBruce Richardson #include <getopt.h> 1799a2dd95SBruce Richardson 1899a2dd95SBruce Richardson #ifdef NEED_USUAL_GETOPT 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson #include <string.h> 2199a2dd95SBruce Richardson #include <stdlib.h> 2299a2dd95SBruce Richardson 23*a06fb0faSStephen Hemminger char *optarg; /* argument associated with option */ 2499a2dd95SBruce Richardson int opterr = 1; /* if error message should be printed */ 2599a2dd95SBruce Richardson int optind = 1; /* index into parent argv vector */ 2699a2dd95SBruce Richardson int optopt = '?'; /* character checked for validity */ 2799a2dd95SBruce Richardson 2899a2dd95SBruce Richardson static void pass(const char *a) {(void) a; } 2999a2dd95SBruce Richardson #define warnx(a, ...) pass(a) 3099a2dd95SBruce Richardson 3199a2dd95SBruce Richardson #define PRINT_ERROR ((opterr) && (*options != ':')) 3299a2dd95SBruce Richardson 3399a2dd95SBruce Richardson #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ 3499a2dd95SBruce Richardson #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ 3599a2dd95SBruce Richardson #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ 3699a2dd95SBruce Richardson 3799a2dd95SBruce Richardson /* return values */ 3899a2dd95SBruce Richardson #define BADCH ((int)'?') 3999a2dd95SBruce Richardson #define BADARG ((*options == ':') ? (int)':' : (int)'?') 4099a2dd95SBruce Richardson #define INORDER 1 4199a2dd95SBruce Richardson 42*a06fb0faSStephen Hemminger static char EMSG[] = ""; 4399a2dd95SBruce Richardson 44*a06fb0faSStephen Hemminger static char *place = EMSG; /* option letter processing */ 4599a2dd95SBruce Richardson 4699a2dd95SBruce Richardson /* XXX: set optreset to 1 rather than these two */ 4799a2dd95SBruce Richardson static int nonopt_start = -1; /* first non option argument (for permute) */ 4899a2dd95SBruce Richardson static int nonopt_end = -1; /* first option after non options (for permute) */ 4999a2dd95SBruce Richardson 5099a2dd95SBruce Richardson /* Error messages */ 5199a2dd95SBruce Richardson static const char recargchar[] = "option requires an argument -- %c"; 5299a2dd95SBruce Richardson static const char recargstring[] = "option requires an argument -- %s"; 5399a2dd95SBruce Richardson static const char ambig[] = "ambiguous option -- %.*s"; 5499a2dd95SBruce Richardson static const char noarg[] = "option doesn't take an argument -- %.*s"; 5599a2dd95SBruce Richardson static const char illoptchar[] = "unknown option -- %c"; 5699a2dd95SBruce Richardson static const char illoptstring[] = "unknown option -- %s"; 5799a2dd95SBruce Richardson 5899a2dd95SBruce Richardson /* 5999a2dd95SBruce Richardson * Compute the greatest common divisor of a and b. 6099a2dd95SBruce Richardson */ 6199a2dd95SBruce Richardson static int 6299a2dd95SBruce Richardson gcd(int a, int b) 6399a2dd95SBruce Richardson { 6499a2dd95SBruce Richardson int c; 6599a2dd95SBruce Richardson 6699a2dd95SBruce Richardson c = a % b; 6799a2dd95SBruce Richardson while (c != 0) { 6899a2dd95SBruce Richardson a = b; 6999a2dd95SBruce Richardson b = c; 7099a2dd95SBruce Richardson c = a % b; 7199a2dd95SBruce Richardson } 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson return (b); 7499a2dd95SBruce Richardson } 7599a2dd95SBruce Richardson 7699a2dd95SBruce Richardson /* 7799a2dd95SBruce Richardson * Exchange the block from nonopt_start to nonopt_end with the block 7899a2dd95SBruce Richardson * from nonopt_end to opt_end (keeping the same order of arguments 7999a2dd95SBruce Richardson * in each block). 8099a2dd95SBruce Richardson */ 8199a2dd95SBruce Richardson static void 8299a2dd95SBruce Richardson permute_args(int panonopt_start, int panonopt_end, int opt_end, 83*a06fb0faSStephen Hemminger char * const *nargv) 8499a2dd95SBruce Richardson { 8599a2dd95SBruce Richardson int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 8699a2dd95SBruce Richardson char *swap; 8799a2dd95SBruce Richardson 8899a2dd95SBruce Richardson /* 8999a2dd95SBruce Richardson * compute lengths of blocks and number and size of cycles 9099a2dd95SBruce Richardson */ 9199a2dd95SBruce Richardson nnonopts = panonopt_end - panonopt_start; 9299a2dd95SBruce Richardson nopts = opt_end - panonopt_end; 9399a2dd95SBruce Richardson ncycle = gcd(nnonopts, nopts); 9499a2dd95SBruce Richardson cyclelen = (opt_end - panonopt_start) / ncycle; 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson for (i = 0; i < ncycle; i++) { 9799a2dd95SBruce Richardson cstart = panonopt_end+i; 9899a2dd95SBruce Richardson pos = cstart; 9999a2dd95SBruce Richardson for (j = 0; j < cyclelen; j++) { 10099a2dd95SBruce Richardson if (pos >= panonopt_end) 10199a2dd95SBruce Richardson pos -= nnonopts; 10299a2dd95SBruce Richardson else 10399a2dd95SBruce Richardson pos += nopts; 104*a06fb0faSStephen Hemminger 10599a2dd95SBruce Richardson swap = nargv[pos]; 10699a2dd95SBruce Richardson /* LINTED const cast */ 107*a06fb0faSStephen Hemminger ((char **)(uintptr_t)nargv)[pos] = nargv[cstart]; 10899a2dd95SBruce Richardson /* LINTED const cast */ 109*a06fb0faSStephen Hemminger ((char **)(uintptr_t)nargv)[cstart] = swap; 11099a2dd95SBruce Richardson } 11199a2dd95SBruce Richardson } 11299a2dd95SBruce Richardson } 11399a2dd95SBruce Richardson 11499a2dd95SBruce Richardson /* 11599a2dd95SBruce Richardson * parse_long_options -- 11699a2dd95SBruce Richardson * Parse long options in argc/argv argument vector. 11799a2dd95SBruce Richardson * Returns -1 if short_too is set and the option does not match long_options. 11899a2dd95SBruce Richardson */ 11999a2dd95SBruce Richardson static int 120*a06fb0faSStephen Hemminger parse_long_options(char * const *nargv, const char *options, 12199a2dd95SBruce Richardson const struct option *long_options, int *idx, int short_too) 12299a2dd95SBruce Richardson { 12399a2dd95SBruce Richardson const char *current_argv; 12499a2dd95SBruce Richardson char *has_equal; 12599a2dd95SBruce Richardson size_t current_argv_len; 12699a2dd95SBruce Richardson int i, match; 12799a2dd95SBruce Richardson 12899a2dd95SBruce Richardson current_argv = place; 12999a2dd95SBruce Richardson match = -1; 13099a2dd95SBruce Richardson 13199a2dd95SBruce Richardson optind++; 13299a2dd95SBruce Richardson 13399a2dd95SBruce Richardson has_equal = strchr(current_argv, '='); 13499a2dd95SBruce Richardson if (has_equal != NULL) { 13599a2dd95SBruce Richardson /* argument found (--option=arg) */ 13699a2dd95SBruce Richardson current_argv_len = has_equal - current_argv; 13799a2dd95SBruce Richardson has_equal++; 13899a2dd95SBruce Richardson } else 13999a2dd95SBruce Richardson current_argv_len = strlen(current_argv); 14099a2dd95SBruce Richardson 14199a2dd95SBruce Richardson for (i = 0; long_options[i].name; i++) { 14299a2dd95SBruce Richardson /* find matching long option */ 14399a2dd95SBruce Richardson if (strncmp(current_argv, long_options[i].name, 14499a2dd95SBruce Richardson current_argv_len)) 14599a2dd95SBruce Richardson continue; 14699a2dd95SBruce Richardson 14799a2dd95SBruce Richardson if (strlen(long_options[i].name) == current_argv_len) { 14899a2dd95SBruce Richardson /* exact match */ 14999a2dd95SBruce Richardson match = i; 15099a2dd95SBruce Richardson break; 15199a2dd95SBruce Richardson } 15299a2dd95SBruce Richardson /* 15399a2dd95SBruce Richardson * If this is a known short option, don't allow 15499a2dd95SBruce Richardson * a partial match of a single character. 15599a2dd95SBruce Richardson */ 15699a2dd95SBruce Richardson if (short_too && current_argv_len == 1) 15799a2dd95SBruce Richardson continue; 15899a2dd95SBruce Richardson 15999a2dd95SBruce Richardson if (match == -1) /* partial match */ 16099a2dd95SBruce Richardson match = i; 16199a2dd95SBruce Richardson else { 16299a2dd95SBruce Richardson /* ambiguous abbreviation */ 16399a2dd95SBruce Richardson if (PRINT_ERROR) 16499a2dd95SBruce Richardson warnx(ambig, (int)current_argv_len, 16599a2dd95SBruce Richardson current_argv); 16699a2dd95SBruce Richardson optopt = 0; 16799a2dd95SBruce Richardson return BADCH; 16899a2dd95SBruce Richardson } 16999a2dd95SBruce Richardson } 17099a2dd95SBruce Richardson if (match != -1) { /* option found */ 17199a2dd95SBruce Richardson if (long_options[match].has_arg == no_argument 17299a2dd95SBruce Richardson && has_equal) { 17399a2dd95SBruce Richardson if (PRINT_ERROR) 17499a2dd95SBruce Richardson warnx(noarg, (int)current_argv_len, 17599a2dd95SBruce Richardson current_argv); 17699a2dd95SBruce Richardson /* 17799a2dd95SBruce Richardson * XXX: GNU sets optopt to val regardless of flag 17899a2dd95SBruce Richardson */ 17999a2dd95SBruce Richardson if (long_options[match].flag == NULL) 18099a2dd95SBruce Richardson optopt = long_options[match].val; 18199a2dd95SBruce Richardson else 18299a2dd95SBruce Richardson optopt = 0; 18399a2dd95SBruce Richardson return BADARG; 18499a2dd95SBruce Richardson } 18599a2dd95SBruce Richardson if (long_options[match].has_arg == required_argument || 18699a2dd95SBruce Richardson long_options[match].has_arg == optional_argument) { 18799a2dd95SBruce Richardson if (has_equal) 18899a2dd95SBruce Richardson optarg = has_equal; 18999a2dd95SBruce Richardson else if (long_options[match].has_arg == 19099a2dd95SBruce Richardson required_argument) { 19199a2dd95SBruce Richardson /* 19299a2dd95SBruce Richardson * optional argument doesn't use next nargv 19399a2dd95SBruce Richardson */ 19499a2dd95SBruce Richardson optarg = nargv[optind++]; 19599a2dd95SBruce Richardson } 19699a2dd95SBruce Richardson } 19799a2dd95SBruce Richardson if ((long_options[match].has_arg == required_argument) 19899a2dd95SBruce Richardson && (optarg == NULL)) { 19999a2dd95SBruce Richardson /* 20099a2dd95SBruce Richardson * Missing argument; leading ':' indicates no error 20199a2dd95SBruce Richardson * should be generated. 20299a2dd95SBruce Richardson */ 20399a2dd95SBruce Richardson if (PRINT_ERROR) 20499a2dd95SBruce Richardson warnx(recargstring, 20599a2dd95SBruce Richardson current_argv); 20699a2dd95SBruce Richardson /* 20799a2dd95SBruce Richardson * XXX: GNU sets optopt to val regardless of flag 20899a2dd95SBruce Richardson */ 20999a2dd95SBruce Richardson if (long_options[match].flag == NULL) 21099a2dd95SBruce Richardson optopt = long_options[match].val; 21199a2dd95SBruce Richardson else 21299a2dd95SBruce Richardson optopt = 0; 21399a2dd95SBruce Richardson --optind; 21499a2dd95SBruce Richardson return BADARG; 21599a2dd95SBruce Richardson } 21699a2dd95SBruce Richardson } else { /* unknown option */ 21799a2dd95SBruce Richardson if (short_too) { 21899a2dd95SBruce Richardson --optind; 21999a2dd95SBruce Richardson return (-1); 22099a2dd95SBruce Richardson } 22199a2dd95SBruce Richardson if (PRINT_ERROR) 22299a2dd95SBruce Richardson warnx(illoptstring, current_argv); 22399a2dd95SBruce Richardson optopt = 0; 22499a2dd95SBruce Richardson return BADCH; 22599a2dd95SBruce Richardson } 22699a2dd95SBruce Richardson if (idx) 22799a2dd95SBruce Richardson *idx = match; 22899a2dd95SBruce Richardson if (long_options[match].flag) { 22999a2dd95SBruce Richardson *long_options[match].flag = long_options[match].val; 23099a2dd95SBruce Richardson return 0; 23199a2dd95SBruce Richardson } else 23299a2dd95SBruce Richardson return (long_options[match].val); 23399a2dd95SBruce Richardson } 23499a2dd95SBruce Richardson 23599a2dd95SBruce Richardson /* 23699a2dd95SBruce Richardson * getopt_internal -- 23799a2dd95SBruce Richardson * Parse argc/argv argument vector. Called by user level routines. 23899a2dd95SBruce Richardson */ 23999a2dd95SBruce Richardson static int 240*a06fb0faSStephen Hemminger getopt_internal(int nargc, char *const nargv[], const char *options, 24199a2dd95SBruce Richardson const struct option *long_options, int *idx, int flags) 24299a2dd95SBruce Richardson { 24399a2dd95SBruce Richardson char *oli; /* option letter list index */ 24499a2dd95SBruce Richardson int optchar, short_too; 24599a2dd95SBruce Richardson static int posixly_correct = -1; 24699a2dd95SBruce Richardson size_t len; 24799a2dd95SBruce Richardson int optreset = 0; 24899a2dd95SBruce Richardson 24999a2dd95SBruce Richardson if (options == NULL) 25099a2dd95SBruce Richardson return (-1); 25199a2dd95SBruce Richardson 25299a2dd95SBruce Richardson /* 25399a2dd95SBruce Richardson * Disable GNU extensions if POSIXLY_CORRECT is set or options 25499a2dd95SBruce Richardson * string begins with a '+'. 25599a2dd95SBruce Richardson */ 25699a2dd95SBruce Richardson if (posixly_correct == -1) { 25799a2dd95SBruce Richardson errno_t err = _wgetenv_s(&len, NULL, 0, L"POSIXLY_CORRECT"); 25899a2dd95SBruce Richardson posixly_correct = (err == 0) && (len > 0); 25999a2dd95SBruce Richardson } 26099a2dd95SBruce Richardson if (!posixly_correct || *options == '+') 26199a2dd95SBruce Richardson flags &= ~FLAG_PERMUTE; 26299a2dd95SBruce Richardson else if (*options == '-') 26399a2dd95SBruce Richardson flags |= FLAG_ALLARGS; 26499a2dd95SBruce Richardson if (*options == '+' || *options == '-') 26599a2dd95SBruce Richardson options++; 26699a2dd95SBruce Richardson /* 26799a2dd95SBruce Richardson * reset if requested 26899a2dd95SBruce Richardson */ 26999a2dd95SBruce Richardson if (optind == 0) 27099a2dd95SBruce Richardson optind = optreset = 1; 27199a2dd95SBruce Richardson 27299a2dd95SBruce Richardson optarg = NULL; 27399a2dd95SBruce Richardson if (optreset) 27499a2dd95SBruce Richardson nonopt_start = nonopt_end = -1; 27599a2dd95SBruce Richardson start: 27699a2dd95SBruce Richardson if (optreset || !*place) { /* update scanning pointer */ 27799a2dd95SBruce Richardson optreset = 0; 27899a2dd95SBruce Richardson if (optind >= nargc) { /* end of argument vector */ 27999a2dd95SBruce Richardson place = EMSG; 28099a2dd95SBruce Richardson if (nonopt_end != -1) { 28199a2dd95SBruce Richardson /* do permutation, if we have to */ 28299a2dd95SBruce Richardson permute_args(nonopt_start, nonopt_end, 28399a2dd95SBruce Richardson optind, nargv); 28499a2dd95SBruce Richardson optind -= nonopt_end - nonopt_start; 28599a2dd95SBruce Richardson } else if (nonopt_start != -1) { 28699a2dd95SBruce Richardson /* 28799a2dd95SBruce Richardson * If we skipped non-options, set optind 28899a2dd95SBruce Richardson * to the first of them. 28999a2dd95SBruce Richardson */ 29099a2dd95SBruce Richardson optind = nonopt_start; 29199a2dd95SBruce Richardson } 29299a2dd95SBruce Richardson nonopt_start = nonopt_end = -1; 29399a2dd95SBruce Richardson return (-1); 29499a2dd95SBruce Richardson } 29599a2dd95SBruce Richardson place = nargv[optind]; 29699a2dd95SBruce Richardson if (*place != '-' || 29799a2dd95SBruce Richardson (place[1] == '\0' && strchr(options, '-') == NULL)) { 29899a2dd95SBruce Richardson place = EMSG; /* found non-option */ 29999a2dd95SBruce Richardson if (flags & FLAG_ALLARGS) { 30099a2dd95SBruce Richardson /* 30199a2dd95SBruce Richardson * GNU extension: 30299a2dd95SBruce Richardson * return non-option as argument to option 1 30399a2dd95SBruce Richardson */ 30499a2dd95SBruce Richardson optarg = nargv[optind++]; 30599a2dd95SBruce Richardson return INORDER; 30699a2dd95SBruce Richardson } 30799a2dd95SBruce Richardson if (!(flags & FLAG_PERMUTE)) { 30899a2dd95SBruce Richardson /* 30999a2dd95SBruce Richardson * If no permutation wanted, stop parsing 31099a2dd95SBruce Richardson * at first non-option. 31199a2dd95SBruce Richardson */ 31299a2dd95SBruce Richardson return (-1); 31399a2dd95SBruce Richardson } 31499a2dd95SBruce Richardson /* do permutation */ 31599a2dd95SBruce Richardson if (nonopt_start == -1) 31699a2dd95SBruce Richardson nonopt_start = optind; 31799a2dd95SBruce Richardson else if (nonopt_end != -1) { 31899a2dd95SBruce Richardson permute_args(nonopt_start, nonopt_end, 31999a2dd95SBruce Richardson optind, nargv); 32099a2dd95SBruce Richardson nonopt_start = optind - 32199a2dd95SBruce Richardson (nonopt_end - nonopt_start); 32299a2dd95SBruce Richardson nonopt_end = -1; 32399a2dd95SBruce Richardson } 32499a2dd95SBruce Richardson optind++; 32599a2dd95SBruce Richardson /* process next argument */ 32699a2dd95SBruce Richardson goto start; 32799a2dd95SBruce Richardson } 32899a2dd95SBruce Richardson if (nonopt_start != -1 && nonopt_end == -1) 32999a2dd95SBruce Richardson nonopt_end = optind; 33099a2dd95SBruce Richardson 33199a2dd95SBruce Richardson /* 33299a2dd95SBruce Richardson * If we have "-" do nothing, if "--" we are done. 33399a2dd95SBruce Richardson */ 33499a2dd95SBruce Richardson if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { 33599a2dd95SBruce Richardson optind++; 33699a2dd95SBruce Richardson place = EMSG; 33799a2dd95SBruce Richardson /* 33899a2dd95SBruce Richardson * We found an option (--), so if we skipped 33999a2dd95SBruce Richardson * non-options, we have to permute. 34099a2dd95SBruce Richardson */ 34199a2dd95SBruce Richardson if (nonopt_end != -1) { 34299a2dd95SBruce Richardson permute_args(nonopt_start, nonopt_end, 34399a2dd95SBruce Richardson optind, nargv); 34499a2dd95SBruce Richardson optind -= nonopt_end - nonopt_start; 34599a2dd95SBruce Richardson } 34699a2dd95SBruce Richardson nonopt_start = nonopt_end = -1; 34799a2dd95SBruce Richardson return (-1); 34899a2dd95SBruce Richardson } 34999a2dd95SBruce Richardson } 35099a2dd95SBruce Richardson 35199a2dd95SBruce Richardson /* 35299a2dd95SBruce Richardson * Check long options if: 35399a2dd95SBruce Richardson * 1) we were passed some 35499a2dd95SBruce Richardson * 2) the arg is not just "-" 35599a2dd95SBruce Richardson * 3) either the arg starts with -- we are getopt_long_only() 35699a2dd95SBruce Richardson */ 35799a2dd95SBruce Richardson if (long_options != NULL && place != nargv[optind] && 35899a2dd95SBruce Richardson (*place == '-' || (flags & FLAG_LONGONLY))) { 35999a2dd95SBruce Richardson short_too = 0; 36099a2dd95SBruce Richardson if (*place == '-') 36199a2dd95SBruce Richardson place++; /* --foo long option */ 36299a2dd95SBruce Richardson else if (*place != ':' && strchr(options, *place) != NULL) 36399a2dd95SBruce Richardson short_too = 1; /* could be short option too */ 36499a2dd95SBruce Richardson 36599a2dd95SBruce Richardson optchar = parse_long_options(nargv, options, long_options, 36699a2dd95SBruce Richardson idx, short_too); 36799a2dd95SBruce Richardson if (optchar != -1) { 36899a2dd95SBruce Richardson place = EMSG; 36999a2dd95SBruce Richardson return optchar; 37099a2dd95SBruce Richardson } 37199a2dd95SBruce Richardson } 37299a2dd95SBruce Richardson 37399a2dd95SBruce Richardson optchar = (int)*place++; 37499a2dd95SBruce Richardson oli = strchr(options, optchar); 37599a2dd95SBruce Richardson if (optchar == (int)':' || 37699a2dd95SBruce Richardson (optchar == (int)'-' && *place != '\0') || 37799a2dd95SBruce Richardson oli == NULL) { 37899a2dd95SBruce Richardson /* 37999a2dd95SBruce Richardson * If the user specified "-" and '-' isn't listed in 38099a2dd95SBruce Richardson * options, return -1 (non-option) as per POSIX. 38199a2dd95SBruce Richardson * Otherwise, it is an unknown option character (or ':'). 38299a2dd95SBruce Richardson */ 38399a2dd95SBruce Richardson if (optchar == (int)'-' && *place == '\0') 38499a2dd95SBruce Richardson return (-1); 38599a2dd95SBruce Richardson if (!*place) 38699a2dd95SBruce Richardson ++optind; 38799a2dd95SBruce Richardson if (PRINT_ERROR) 38899a2dd95SBruce Richardson warnx(illoptchar, optchar); 38999a2dd95SBruce Richardson optopt = optchar; 39099a2dd95SBruce Richardson return BADCH; 39199a2dd95SBruce Richardson } 39299a2dd95SBruce Richardson if (long_options != NULL && optchar == 'W' && oli[1] == ';') { 39399a2dd95SBruce Richardson /* -W long-option */ 39499a2dd95SBruce Richardson if (*place) 39599a2dd95SBruce Richardson ; 39699a2dd95SBruce Richardson else if (++optind >= nargc) { /* no arg */ 39799a2dd95SBruce Richardson place = EMSG; 39899a2dd95SBruce Richardson if (PRINT_ERROR) 39999a2dd95SBruce Richardson warnx(recargchar, optchar); 40099a2dd95SBruce Richardson optopt = optchar; 40199a2dd95SBruce Richardson return BADARG; 40299a2dd95SBruce Richardson } /* white space */ 40399a2dd95SBruce Richardson place = nargv[optind]; 40499a2dd95SBruce Richardson optchar = parse_long_options(nargv, options, long_options, 40599a2dd95SBruce Richardson idx, 0); 40699a2dd95SBruce Richardson place = EMSG; 40799a2dd95SBruce Richardson return optchar; 40899a2dd95SBruce Richardson } 40999a2dd95SBruce Richardson if (*++oli != ':') { /* doesn't take argument */ 41099a2dd95SBruce Richardson if (!*place) 41199a2dd95SBruce Richardson ++optind; 41299a2dd95SBruce Richardson } else { /* takes (optional) argument */ 41399a2dd95SBruce Richardson optarg = NULL; 41499a2dd95SBruce Richardson if (*place) /* no white space */ 41599a2dd95SBruce Richardson optarg = place; 41699a2dd95SBruce Richardson else if (oli[1] != ':') { /* arg not optional */ 41799a2dd95SBruce Richardson if (++optind >= nargc) { /* no arg */ 41899a2dd95SBruce Richardson place = EMSG; 41999a2dd95SBruce Richardson if (PRINT_ERROR) 42099a2dd95SBruce Richardson warnx(recargchar, optchar); 42199a2dd95SBruce Richardson optopt = optchar; 42299a2dd95SBruce Richardson return BADARG; 42399a2dd95SBruce Richardson } 42499a2dd95SBruce Richardson optarg = nargv[optind]; 42599a2dd95SBruce Richardson } 42699a2dd95SBruce Richardson place = EMSG; 42799a2dd95SBruce Richardson ++optind; 42899a2dd95SBruce Richardson } 42999a2dd95SBruce Richardson /* dump back option letter */ 43099a2dd95SBruce Richardson return optchar; 43199a2dd95SBruce Richardson } 43299a2dd95SBruce Richardson 43399a2dd95SBruce Richardson /* 43499a2dd95SBruce Richardson * getopt -- 43599a2dd95SBruce Richardson * Parse argc/argv argument vector. 43699a2dd95SBruce Richardson */ 43799a2dd95SBruce Richardson int 438*a06fb0faSStephen Hemminger getopt(int nargc, char *const nargv[], const char *options) 43999a2dd95SBruce Richardson { 44099a2dd95SBruce Richardson return getopt_internal(nargc, nargv, options, NULL, NULL, 44199a2dd95SBruce Richardson FLAG_PERMUTE); 44299a2dd95SBruce Richardson } 44399a2dd95SBruce Richardson 44499a2dd95SBruce Richardson /* 44599a2dd95SBruce Richardson * getopt_long -- 44699a2dd95SBruce Richardson * Parse argc/argv argument vector. 44799a2dd95SBruce Richardson */ 44899a2dd95SBruce Richardson int 449*a06fb0faSStephen Hemminger getopt_long(int nargc, char *const nargv[], const char *options, 45099a2dd95SBruce Richardson const struct option *long_options, int *idx) 45199a2dd95SBruce Richardson { 45299a2dd95SBruce Richardson 45399a2dd95SBruce Richardson return (getopt_internal(nargc, nargv, options, long_options, idx, 45499a2dd95SBruce Richardson FLAG_PERMUTE)); 45599a2dd95SBruce Richardson } 45699a2dd95SBruce Richardson 45799a2dd95SBruce Richardson /* 45899a2dd95SBruce Richardson * getopt_long_only -- 45999a2dd95SBruce Richardson * Parse argc/argv argument vector. 46099a2dd95SBruce Richardson */ 46199a2dd95SBruce Richardson int 462*a06fb0faSStephen Hemminger getopt_long_only(int nargc, char *const nargv[], const char *options, 46399a2dd95SBruce Richardson const struct option *long_options, int *idx) 46499a2dd95SBruce Richardson { 46599a2dd95SBruce Richardson 46699a2dd95SBruce Richardson return (getopt_internal(nargc, nargv, options, long_options, idx, 46799a2dd95SBruce Richardson FLAG_PERMUTE|FLAG_LONGONLY)); 46899a2dd95SBruce Richardson } 46999a2dd95SBruce Richardson 47099a2dd95SBruce Richardson #endif /* NEED_USUAL_GETOPT */ 471