1268355Sache/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */ 2104128Seric/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ 3104128Seric 4126189Sache/* 5126189Sache * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> 6126189Sache * 7126189Sache * Permission to use, copy, modify, and distribute this software for any 8126189Sache * purpose with or without fee is hereby granted, provided that the above 9126189Sache * copyright notice and this permission notice appear in all copies. 10126189Sache * 11126189Sache * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12126189Sache * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13126189Sache * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14126189Sache * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15126189Sache * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16126189Sache * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17126189Sache * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18126189Sache * 19126189Sache * Sponsored in part by the Defense Advanced Research Projects 20126189Sache * Agency (DARPA) and Air Force Research Laboratory, Air Force 21126189Sache * Materiel Command, USAF, under agreement number F39502-99-1-0512. 22126189Sache */ 23104128Seric/*- 24104128Seric * Copyright (c) 2000 The NetBSD Foundation, Inc. 25104128Seric * All rights reserved. 26104128Seric * 27104128Seric * This code is derived from software contributed to The NetBSD Foundation 28104128Seric * by Dieter Baron and Thomas Klausner. 29104128Seric * 30104128Seric * Redistribution and use in source and binary forms, with or without 31104128Seric * modification, are permitted provided that the following conditions 32104128Seric * are met: 33104128Seric * 1. Redistributions of source code must retain the above copyright 34104128Seric * notice, this list of conditions and the following disclaimer. 35104128Seric * 2. Redistributions in binary form must reproduce the above copyright 36104128Seric * notice, this list of conditions and the following disclaimer in the 37104128Seric * documentation and/or other materials provided with the distribution. 38104128Seric * 39104128Seric * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 40104128Seric * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 41104128Seric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42104128Seric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 43104128Seric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 44104128Seric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 45104128Seric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 46104128Seric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47104128Seric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48104128Seric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 49104128Seric * POSSIBILITY OF SUCH DAMAGE. 50104128Seric */ 51104128Seric 52126189Sache#if 0 53104128Seric#if defined(LIBC_SCCS) && !defined(lint) 54126189Sachestatic char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; 55104128Seric#endif /* LIBC_SCCS and not lint */ 56126189Sache#endif 57126189Sache#include <sys/cdefs.h> 58126189Sache__FBSDID("$FreeBSD$"); 59104128Seric 60104128Seric#include <err.h> 61104128Seric#include <errno.h> 62104128Seric#include <getopt.h> 63104128Seric#include <stdlib.h> 64104128Seric#include <string.h> 65104128Seric 66126452Sache#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ 67126452Sache 68162574Sache#if 0 /* we prefer to keep our getopt(3) */ 69126189Sache#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ 70104128Seric#endif 71104128Seric 72104128Seric#ifdef REPLACE_GETOPT 73104128Sericint opterr = 1; /* if error message should be printed */ 74104128Sericint optind = 1; /* index into parent argv vector */ 75104128Sericint optopt = '?'; /* character checked for validity */ 76104128Sericint optreset; /* reset getopt */ 77104128Sericchar *optarg; /* argument associated with option */ 78104128Seric#endif 79104128Seric 80126189Sache#define PRINT_ERROR ((opterr) && (*options != ':')) 81104128Seric 82126189Sache#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ 83126189Sache#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ 84126189Sache#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ 85104128Seric 86104128Seric/* return values */ 87126189Sache#define BADCH (int)'?' 88126189Sache#define BADARG ((*options == ':') ? (int)':' : (int)'?') 89126189Sache#define INORDER (int)1 90104128Seric 91126189Sache#define EMSG "" 92104128Seric 93126518Sache#ifdef GNU_COMPATIBLE 94126518Sache#define NO_PREFIX (-1) 95126518Sache#define D_PREFIX 0 96126518Sache#define DD_PREFIX 1 97126518Sache#define W_PREFIX 2 98126518Sache#endif 99126518Sache 100126189Sachestatic int getopt_internal(int, char * const *, const char *, 101126189Sache const struct option *, int *, int); 102126189Sachestatic int parse_long_options(char * const *, const char *, 103127733Sache const struct option *, int *, int, int); 104105299Salfredstatic int gcd(int, int); 105105299Salfredstatic void permute_args(int, int, int, char * const *); 106104128Seric 107104128Sericstatic char *place = EMSG; /* option letter processing */ 108104128Seric 109104128Seric/* XXX: set optreset to 1 rather than these two */ 110104128Sericstatic int nonopt_start = -1; /* first non option argument (for permute) */ 111104128Sericstatic int nonopt_end = -1; /* first option after non options (for permute) */ 112104128Seric 113104128Seric/* Error messages */ 114104128Sericstatic const char recargchar[] = "option requires an argument -- %c"; 115126518Sachestatic const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ 116126452Sache#ifdef GNU_COMPATIBLE 117126518Sachestatic int dash_prefix = NO_PREFIX; 118126452Sachestatic const char gnuoptchar[] = "invalid option -- %c"; 119126452Sache 120126518Sachestatic const char recargstring[] = "option `%s%s' requires an argument"; 121126518Sachestatic const char ambig[] = "option `%s%.*s' is ambiguous"; 122126518Sachestatic const char noarg[] = "option `%s%.*s' doesn't allow an argument"; 123126518Sachestatic const char illoptstring[] = "unrecognized option `%s%s'"; 124126452Sache#else 125104128Sericstatic const char recargstring[] = "option requires an argument -- %s"; 126104128Sericstatic const char ambig[] = "ambiguous option -- %.*s"; 127104128Sericstatic const char noarg[] = "option doesn't take an argument -- %.*s"; 128104128Sericstatic const char illoptstring[] = "unknown option -- %s"; 129126452Sache#endif 130104128Seric 131104128Seric/* 132104128Seric * Compute the greatest common divisor of a and b. 133104128Seric */ 134104128Sericstatic int 135126189Sachegcd(int a, int b) 136104128Seric{ 137104128Seric int c; 138104128Seric 139104128Seric c = a % b; 140104128Seric while (c != 0) { 141104128Seric a = b; 142104128Seric b = c; 143104128Seric c = a % b; 144104128Seric } 145126189Sache 146126189Sache return (b); 147104128Seric} 148104128Seric 149104128Seric/* 150104128Seric * Exchange the block from nonopt_start to nonopt_end with the block 151104128Seric * from nonopt_end to opt_end (keeping the same order of arguments 152104128Seric * in each block). 153104128Seric */ 154104128Sericstatic void 155126189Sachepermute_args(int panonopt_start, int panonopt_end, int opt_end, 156126189Sache char * const *nargv) 157104128Seric{ 158104128Seric int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 159104128Seric char *swap; 160104128Seric 161104128Seric /* 162104128Seric * compute lengths of blocks and number and size of cycles 163104128Seric */ 164104128Seric nnonopts = panonopt_end - panonopt_start; 165104128Seric nopts = opt_end - panonopt_end; 166104128Seric ncycle = gcd(nnonopts, nopts); 167104128Seric cyclelen = (opt_end - panonopt_start) / ncycle; 168104128Seric 169104128Seric for (i = 0; i < ncycle; i++) { 170104128Seric cstart = panonopt_end+i; 171104128Seric pos = cstart; 172104128Seric for (j = 0; j < cyclelen; j++) { 173104128Seric if (pos >= panonopt_end) 174104128Seric pos -= nnonopts; 175104128Seric else 176104128Seric pos += nopts; 177104128Seric swap = nargv[pos]; 178104128Seric /* LINTED const cast */ 179104128Seric ((char **) nargv)[pos] = nargv[cstart]; 180104128Seric /* LINTED const cast */ 181104128Seric ((char **)nargv)[cstart] = swap; 182104128Seric } 183104128Seric } 184104128Seric} 185104128Seric 186104128Seric/* 187126189Sache * parse_long_options -- 188126189Sache * Parse long options in argc/argv argument vector. 189126189Sache * Returns -1 if short_too is set and the option does not match long_options. 190126189Sache */ 191126189Sachestatic int 192126189Sacheparse_long_options(char * const *nargv, const char *options, 193127733Sache const struct option *long_options, int *idx, int short_too, int flags) 194126189Sache{ 195126189Sache char *current_argv, *has_equal; 196126518Sache#ifdef GNU_COMPATIBLE 197126518Sache char *current_dash; 198126518Sache#endif 199126189Sache size_t current_argv_len; 200127733Sache int i, match, exact_match, second_partial_match; 201126189Sache 202126189Sache current_argv = place; 203126518Sache#ifdef GNU_COMPATIBLE 204126518Sache switch (dash_prefix) { 205126518Sache case D_PREFIX: 206126518Sache current_dash = "-"; 207126518Sache break; 208126518Sache case DD_PREFIX: 209126518Sache current_dash = "--"; 210126518Sache break; 211126518Sache case W_PREFIX: 212126518Sache current_dash = "-W "; 213126518Sache break; 214126518Sache default: 215126518Sache current_dash = ""; 216126518Sache break; 217126518Sache } 218126518Sache#endif 219126189Sache match = -1; 220127733Sache exact_match = 0; 221127733Sache second_partial_match = 0; 222126189Sache 223126189Sache optind++; 224126189Sache 225126189Sache if ((has_equal = strchr(current_argv, '=')) != NULL) { 226126189Sache /* argument found (--option=arg) */ 227126189Sache current_argv_len = has_equal - current_argv; 228126189Sache has_equal++; 229126189Sache } else 230126189Sache current_argv_len = strlen(current_argv); 231126189Sache 232126189Sache for (i = 0; long_options[i].name; i++) { 233126189Sache /* find matching long option */ 234126189Sache if (strncmp(current_argv, long_options[i].name, 235126189Sache current_argv_len)) 236126189Sache continue; 237126189Sache 238126189Sache if (strlen(long_options[i].name) == current_argv_len) { 239126189Sache /* exact match */ 240126189Sache match = i; 241127733Sache exact_match = 1; 242126189Sache break; 243126189Sache } 244126189Sache /* 245126189Sache * If this is a known short option, don't allow 246126189Sache * a partial match of a single character. 247126189Sache */ 248127734Sache if (short_too && current_argv_len == 1) 249126189Sache continue; 250126189Sache 251268355Sache if (match == -1) /* first partial match */ 252126189Sache match = i; 253127733Sache else if ((flags & FLAG_LONGONLY) || 254127733Sache long_options[i].has_arg != 255127733Sache long_options[match].has_arg || 256127733Sache long_options[i].flag != long_options[match].flag || 257127733Sache long_options[i].val != long_options[match].val) 258127733Sache second_partial_match = 1; 259127733Sache } 260127733Sache if (!exact_match && second_partial_match) { 261127733Sache /* ambiguous abbreviation */ 262127733Sache if (PRINT_ERROR) 263127733Sache warnx(ambig, 264126518Sache#ifdef GNU_COMPATIBLE 265127733Sache current_dash, 266126518Sache#endif 267127733Sache (int)current_argv_len, 268127733Sache current_argv); 269127733Sache optopt = 0; 270127733Sache return (BADCH); 271126189Sache } 272126189Sache if (match != -1) { /* option found */ 273126189Sache if (long_options[match].has_arg == no_argument 274126189Sache && has_equal) { 275126189Sache if (PRINT_ERROR) 276126518Sache warnx(noarg, 277126518Sache#ifdef GNU_COMPATIBLE 278126518Sache current_dash, 279126518Sache#endif 280126518Sache (int)current_argv_len, 281126189Sache current_argv); 282126189Sache /* 283126189Sache * XXX: GNU sets optopt to val regardless of flag 284126189Sache */ 285126189Sache if (long_options[match].flag == NULL) 286126189Sache optopt = long_options[match].val; 287126189Sache else 288126189Sache optopt = 0; 289126535Sache#ifdef GNU_COMPATIBLE 290126535Sache return (BADCH); 291126535Sache#else 292126189Sache return (BADARG); 293126535Sache#endif 294126189Sache } 295126189Sache if (long_options[match].has_arg == required_argument || 296126189Sache long_options[match].has_arg == optional_argument) { 297126189Sache if (has_equal) 298126189Sache optarg = has_equal; 299126189Sache else if (long_options[match].has_arg == 300126189Sache required_argument) { 301126189Sache /* 302126189Sache * optional argument doesn't use next nargv 303126189Sache */ 304126189Sache optarg = nargv[optind++]; 305126189Sache } 306126189Sache } 307126189Sache if ((long_options[match].has_arg == required_argument) 308126189Sache && (optarg == NULL)) { 309126189Sache /* 310126189Sache * Missing argument; leading ':' indicates no error 311126189Sache * should be generated. 312126189Sache */ 313126189Sache if (PRINT_ERROR) 314126189Sache warnx(recargstring, 315126518Sache#ifdef GNU_COMPATIBLE 316126518Sache current_dash, 317126518Sache#endif 318126189Sache current_argv); 319126189Sache /* 320126189Sache * XXX: GNU sets optopt to val regardless of flag 321126189Sache */ 322126189Sache if (long_options[match].flag == NULL) 323126189Sache optopt = long_options[match].val; 324126189Sache else 325126189Sache optopt = 0; 326126189Sache --optind; 327126189Sache return (BADARG); 328126189Sache } 329126189Sache } else { /* unknown option */ 330126189Sache if (short_too) { 331126189Sache --optind; 332126189Sache return (-1); 333126189Sache } 334126189Sache if (PRINT_ERROR) 335126518Sache warnx(illoptstring, 336126518Sache#ifdef GNU_COMPATIBLE 337126518Sache current_dash, 338126518Sache#endif 339126518Sache current_argv); 340126189Sache optopt = 0; 341126189Sache return (BADCH); 342126189Sache } 343126189Sache if (idx) 344126189Sache *idx = match; 345126189Sache if (long_options[match].flag) { 346126189Sache *long_options[match].flag = long_options[match].val; 347126189Sache return (0); 348126189Sache } else 349126189Sache return (long_options[match].val); 350126189Sache} 351126189Sache 352126189Sache/* 353104128Seric * getopt_internal -- 354104128Seric * Parse argc/argv argument vector. Called by user level routines. 355104128Seric */ 356104128Sericstatic int 357126189Sachegetopt_internal(int nargc, char * const *nargv, const char *options, 358126189Sache const struct option *long_options, int *idx, int flags) 359104128Seric{ 360104128Seric char *oli; /* option letter list index */ 361126189Sache int optchar, short_too; 362268355Sache static int posixly_correct = -1; 363104128Seric 364126189Sache if (options == NULL) 365126189Sache return (-1); 366104128Seric 367126189Sache /* 368268355Sache * XXX Some GNU programs (like cvs) set optind to 0 instead of 369268355Sache * XXX using optreset. Work around this braindamage. 370268355Sache */ 371268355Sache if (optind == 0) 372268355Sache optind = optreset = 1; 373268355Sache 374268355Sache /* 375126189Sache * Disable GNU extensions if POSIXLY_CORRECT is set or options 376126189Sache * string begins with a '+'. 377126189Sache */ 378268355Sache if (posixly_correct == -1 || optreset) 379268355Sache posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); 380126452Sache if (*options == '-') 381126452Sache flags |= FLAG_ALLARGS; 382126452Sache else if (posixly_correct || *options == '+') 383126452Sache flags &= ~FLAG_PERMUTE; 384126189Sache if (*options == '+' || *options == '-') 385126189Sache options++; 386104128Seric 387126189Sache optarg = NULL; 388104128Seric if (optreset) 389104128Seric nonopt_start = nonopt_end = -1; 390104128Sericstart: 391104128Seric if (optreset || !*place) { /* update scanning pointer */ 392104128Seric optreset = 0; 393104128Seric if (optind >= nargc) { /* end of argument vector */ 394104128Seric place = EMSG; 395104128Seric if (nonopt_end != -1) { 396104128Seric /* do permutation, if we have to */ 397104128Seric permute_args(nonopt_start, nonopt_end, 398104128Seric optind, nargv); 399104128Seric optind -= nonopt_end - nonopt_start; 400104128Seric } 401104128Seric else if (nonopt_start != -1) { 402104128Seric /* 403104128Seric * If we skipped non-options, set optind 404104128Seric * to the first of them. 405104128Seric */ 406104128Seric optind = nonopt_start; 407104128Seric } 408104128Seric nonopt_start = nonopt_end = -1; 409126189Sache return (-1); 410104128Seric } 411126189Sache if (*(place = nargv[optind]) != '-' || 412126692Sache#ifdef GNU_COMPATIBLE 413126692Sache place[1] == '\0') { 414126692Sache#else 415126189Sache (place[1] == '\0' && strchr(options, '-') == NULL)) { 416126692Sache#endif 417126189Sache place = EMSG; /* found non-option */ 418126189Sache if (flags & FLAG_ALLARGS) { 419104128Seric /* 420126189Sache * GNU extension: 421104128Seric * return non-option as argument to option 1 422104128Seric */ 423104128Seric optarg = nargv[optind++]; 424126189Sache return (INORDER); 425104128Seric } 426126189Sache if (!(flags & FLAG_PERMUTE)) { 427104128Seric /* 428126189Sache * If no permutation wanted, stop parsing 429126189Sache * at first non-option. 430104128Seric */ 431126189Sache return (-1); 432104128Seric } 433104128Seric /* do permutation */ 434104128Seric if (nonopt_start == -1) 435104128Seric nonopt_start = optind; 436104128Seric else if (nonopt_end != -1) { 437104128Seric permute_args(nonopt_start, nonopt_end, 438104128Seric optind, nargv); 439104128Seric nonopt_start = optind - 440104128Seric (nonopt_end - nonopt_start); 441104128Seric nonopt_end = -1; 442104128Seric } 443104128Seric optind++; 444104128Seric /* process next argument */ 445104128Seric goto start; 446104128Seric } 447104128Seric if (nonopt_start != -1 && nonopt_end == -1) 448104128Seric nonopt_end = optind; 449126189Sache 450126189Sache /* 451126189Sache * If we have "-" do nothing, if "--" we are done. 452126189Sache */ 453126189Sache if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { 454126189Sache optind++; 455126189Sache place = EMSG; 456126189Sache /* 457126189Sache * We found an option (--), so if we skipped 458126189Sache * non-options, we have to permute. 459126189Sache */ 460126189Sache if (nonopt_end != -1) { 461126189Sache permute_args(nonopt_start, nonopt_end, 462126189Sache optind, nargv); 463126189Sache optind -= nonopt_end - nonopt_start; 464126189Sache } 465126189Sache nonopt_start = nonopt_end = -1; 466126189Sache return (-1); 467104128Seric } 468104128Seric } 469126189Sache 470126189Sache /* 471126189Sache * Check long options if: 472126189Sache * 1) we were passed some 473126189Sache * 2) the arg is not just "-" 474126189Sache * 3) either the arg starts with -- we are getopt_long_only() 475126189Sache */ 476126189Sache if (long_options != NULL && place != nargv[optind] && 477126189Sache (*place == '-' || (flags & FLAG_LONGONLY))) { 478126189Sache short_too = 0; 479126518Sache#ifdef GNU_COMPATIBLE 480126518Sache dash_prefix = D_PREFIX; 481126518Sache#endif 482126518Sache if (*place == '-') { 483126189Sache place++; /* --foo long option */ 484126518Sache#ifdef GNU_COMPATIBLE 485126518Sache dash_prefix = DD_PREFIX; 486126518Sache#endif 487126518Sache } else if (*place != ':' && strchr(options, *place) != NULL) 488126189Sache short_too = 1; /* could be short option too */ 489126189Sache 490126189Sache optchar = parse_long_options(nargv, options, long_options, 491127733Sache idx, short_too, flags); 492126189Sache if (optchar != -1) { 493126189Sache place = EMSG; 494126189Sache return (optchar); 495126189Sache } 496126189Sache } 497126189Sache 498104128Seric if ((optchar = (int)*place++) == (int)':' || 499126189Sache (optchar == (int)'-' && *place != '\0') || 500126189Sache (oli = strchr(options, optchar)) == NULL) { 501126189Sache /* 502126189Sache * If the user specified "-" and '-' isn't listed in 503126189Sache * options, return -1 (non-option) as per POSIX. 504126189Sache * Otherwise, it is an unknown option character (or ':'). 505126189Sache */ 506126189Sache if (optchar == (int)'-' && *place == '\0') 507126189Sache return (-1); 508104128Seric if (!*place) 509104128Seric ++optind; 510126452Sache#ifdef GNU_COMPATIBLE 511104128Seric if (PRINT_ERROR) 512126452Sache warnx(posixly_correct ? illoptchar : gnuoptchar, 513126452Sache optchar); 514126452Sache#else 515126452Sache if (PRINT_ERROR) 516104128Seric warnx(illoptchar, optchar); 517126452Sache#endif 518104128Seric optopt = optchar; 519126189Sache return (BADCH); 520104128Seric } 521126189Sache if (long_options != NULL && optchar == 'W' && oli[1] == ';') { 522126189Sache /* -W long-option */ 523126189Sache if (*place) /* no space */ 524126189Sache /* NOTHING */; 525126189Sache else if (++optind >= nargc) { /* no arg */ 526104128Seric place = EMSG; 527104128Seric if (PRINT_ERROR) 528104128Seric warnx(recargchar, optchar); 529104128Seric optopt = optchar; 530126189Sache return (BADARG); 531104128Seric } else /* white space */ 532104128Seric place = nargv[optind]; 533126518Sache#ifdef GNU_COMPATIBLE 534126518Sache dash_prefix = W_PREFIX; 535126518Sache#endif 536126189Sache optchar = parse_long_options(nargv, options, long_options, 537127733Sache idx, 0, flags); 538126189Sache place = EMSG; 539126189Sache return (optchar); 540104128Seric } 541104128Seric if (*++oli != ':') { /* doesn't take argument */ 542104128Seric if (!*place) 543104128Seric ++optind; 544104128Seric } else { /* takes (optional) argument */ 545104128Seric optarg = NULL; 546104128Seric if (*place) /* no white space */ 547104128Seric optarg = place; 548104128Seric else if (oli[1] != ':') { /* arg not optional */ 549104128Seric if (++optind >= nargc) { /* no arg */ 550104128Seric place = EMSG; 551104128Seric if (PRINT_ERROR) 552104128Seric warnx(recargchar, optchar); 553104128Seric optopt = optchar; 554126189Sache return (BADARG); 555104128Seric } else 556104128Seric optarg = nargv[optind]; 557162555Sache } 558104128Seric place = EMSG; 559104128Seric ++optind; 560104128Seric } 561104128Seric /* dump back option letter */ 562126189Sache return (optchar); 563104128Seric} 564104128Seric 565104128Seric#ifdef REPLACE_GETOPT 566104128Seric/* 567104128Seric * getopt -- 568104128Seric * Parse argc/argv argument vector. 569104128Seric * 570126189Sache * [eventually this will replace the BSD getopt] 571104128Seric */ 572104128Sericint 573126189Sachegetopt(int nargc, char * const *nargv, const char *options) 574104128Seric{ 575104128Seric 576126189Sache /* 577126189Sache * We don't pass FLAG_PERMUTE to getopt_internal() since 578126189Sache * the BSD getopt(3) (unlike GNU) has never done this. 579126189Sache * 580126189Sache * Furthermore, since many privileged programs call getopt() 581126189Sache * before dropping privileges it makes sense to keep things 582126189Sache * as simple (and bug-free) as possible. 583126189Sache */ 584126189Sache return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); 585104128Seric} 586126189Sache#endif /* REPLACE_GETOPT */ 587104128Seric 588104128Seric/* 589104128Seric * getopt_long -- 590104128Seric * Parse argc/argv argument vector. 591104128Seric */ 592104128Sericint 593162574Sachegetopt_long(int nargc, char * const *nargv, const char *options, 594162574Sache const struct option *long_options, int *idx) 595104128Seric{ 596104128Seric 597126189Sache return (getopt_internal(nargc, nargv, options, long_options, idx, 598126189Sache FLAG_PERMUTE)); 599126189Sache} 600104128Seric 601126189Sache/* 602126189Sache * getopt_long_only -- 603126189Sache * Parse argc/argv argument vector. 604126189Sache */ 605126189Sacheint 606162574Sachegetopt_long_only(int nargc, char * const *nargv, const char *options, 607162574Sache const struct option *long_options, int *idx) 608126189Sache{ 609104128Seric 610126189Sache return (getopt_internal(nargc, nargv, options, long_options, idx, 611126189Sache FLAG_PERMUTE|FLAG_LONGONLY)); 612104128Seric} 613