1*3106aed5Smillert /* $OpenBSD: getopt_long.c,v 1.4 2002/12/05 22:26:04 millert Exp $ */ 247f6c619Smillert /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ 347f6c619Smillert 447f6c619Smillert /*- 547f6c619Smillert * Copyright (c) 2000 The NetBSD Foundation, Inc. 647f6c619Smillert * All rights reserved. 747f6c619Smillert * 847f6c619Smillert * This code is derived from software contributed to The NetBSD Foundation 947f6c619Smillert * by Dieter Baron and Thomas Klausner. 1047f6c619Smillert * 1147f6c619Smillert * Redistribution and use in source and binary forms, with or without 1247f6c619Smillert * modification, are permitted provided that the following conditions 1347f6c619Smillert * are met: 1447f6c619Smillert * 1. Redistributions of source code must retain the above copyright 1547f6c619Smillert * notice, this list of conditions and the following disclaimer. 1647f6c619Smillert * 2. Redistributions in binary form must reproduce the above copyright 1747f6c619Smillert * notice, this list of conditions and the following disclaimer in the 1847f6c619Smillert * documentation and/or other materials provided with the distribution. 1947f6c619Smillert * 3. All advertising materials mentioning features or use of this software 2047f6c619Smillert * must display the following acknowledgement: 2147f6c619Smillert * This product includes software developed by the NetBSD 2247f6c619Smillert * Foundation, Inc. and its contributors. 2347f6c619Smillert * 4. Neither the name of The NetBSD Foundation nor the names of its 2447f6c619Smillert * contributors may be used to endorse or promote products derived 2547f6c619Smillert * from this software without specific prior written permission. 2647f6c619Smillert * 2747f6c619Smillert * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2847f6c619Smillert * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2947f6c619Smillert * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3047f6c619Smillert * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3147f6c619Smillert * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3247f6c619Smillert * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3347f6c619Smillert * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3447f6c619Smillert * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3547f6c619Smillert * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3647f6c619Smillert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3747f6c619Smillert * POSSIBILITY OF SUCH DAMAGE. 3847f6c619Smillert */ 3947f6c619Smillert 4047f6c619Smillert #if defined(LIBC_SCCS) && !defined(lint) 41*3106aed5Smillert static char *rcsid = "$OpenBSD: getopt_long.c,v 1.4 2002/12/05 22:26:04 millert Exp $"; 4247f6c619Smillert #endif /* LIBC_SCCS and not lint */ 4347f6c619Smillert 4447f6c619Smillert #include <err.h> 4547f6c619Smillert #include <errno.h> 4647f6c619Smillert #include <getopt.h> 4747f6c619Smillert #include <stdlib.h> 4847f6c619Smillert #include <string.h> 4947f6c619Smillert 503f02fa7aSmillert #ifdef REPLACE_GETOPT 5147f6c619Smillert int opterr = 1; /* if error message should be printed */ 5247f6c619Smillert int optind = 1; /* index into parent argv vector */ 5347f6c619Smillert int optopt = '?'; /* character checked for validity */ 5447f6c619Smillert int optreset; /* reset getopt */ 5547f6c619Smillert char *optarg; /* argument associated with option */ 563f02fa7aSmillert #endif 5747f6c619Smillert 5847f6c619Smillert #define PRINT_ERROR ((opterr) && (*options != ':')) 5947f6c619Smillert 60a4cca5d9Smillert #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ 61a4cca5d9Smillert #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ 62a4cca5d9Smillert #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ 6347f6c619Smillert 6447f6c619Smillert /* return values */ 6547f6c619Smillert #define BADCH (int)'?' 6647f6c619Smillert #define BADARG ((*options == ':') ? (int)':' : (int)'?') 6747f6c619Smillert #define INORDER (int)1 6847f6c619Smillert 6947f6c619Smillert #define EMSG "" 7047f6c619Smillert 71a4cca5d9Smillert static int getopt_internal(int, char * const *, const char *, 72a4cca5d9Smillert const struct option *, int *, int); 73a4cca5d9Smillert static int parse_long_options(int, char * const *, const char *, 7447f6c619Smillert const struct option *, int *, int); 7547f6c619Smillert static int gcd(int, int); 7647f6c619Smillert static void permute_args(int, int, int, char * const *); 7747f6c619Smillert 7847f6c619Smillert static char *place = EMSG; /* option letter processing */ 7947f6c619Smillert 8047f6c619Smillert /* XXX: set optreset to 1 rather than these two */ 8147f6c619Smillert static int nonopt_start = -1; /* first non option argument (for permute) */ 8247f6c619Smillert static int nonopt_end = -1; /* first option after non options (for permute) */ 8347f6c619Smillert 8447f6c619Smillert /* Error messages */ 8547f6c619Smillert static const char recargchar[] = "option requires an argument -- %c"; 8647f6c619Smillert static const char recargstring[] = "option requires an argument -- %s"; 8747f6c619Smillert static const char ambig[] = "ambiguous option -- %.*s"; 8847f6c619Smillert static const char noarg[] = "option doesn't take an argument -- %.*s"; 8947f6c619Smillert static const char illoptchar[] = "unknown option -- %c"; 9047f6c619Smillert static const char illoptstring[] = "unknown option -- %s"; 9147f6c619Smillert 9247f6c619Smillert /* 9347f6c619Smillert * Compute the greatest common divisor of a and b. 9447f6c619Smillert */ 9547f6c619Smillert static int 96a4cca5d9Smillert gcd(int a, int b) 9747f6c619Smillert { 9847f6c619Smillert int c; 9947f6c619Smillert 10047f6c619Smillert c = a % b; 10147f6c619Smillert while (c != 0) { 10247f6c619Smillert a = b; 10347f6c619Smillert b = c; 10447f6c619Smillert c = a % b; 10547f6c619Smillert } 10647f6c619Smillert 107a4cca5d9Smillert return (b); 10847f6c619Smillert } 10947f6c619Smillert 11047f6c619Smillert /* 11147f6c619Smillert * Exchange the block from nonopt_start to nonopt_end with the block 11247f6c619Smillert * from nonopt_end to opt_end (keeping the same order of arguments 11347f6c619Smillert * in each block). 11447f6c619Smillert */ 11547f6c619Smillert static void 116a4cca5d9Smillert permute_args(int panonopt_start, int panonopt_end, int opt_end, 117a4cca5d9Smillert char * const *nargv) 11847f6c619Smillert { 11947f6c619Smillert int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 12047f6c619Smillert char *swap; 12147f6c619Smillert 12247f6c619Smillert /* 12347f6c619Smillert * compute lengths of blocks and number and size of cycles 12447f6c619Smillert */ 12547f6c619Smillert nnonopts = panonopt_end - panonopt_start; 12647f6c619Smillert nopts = opt_end - panonopt_end; 12747f6c619Smillert ncycle = gcd(nnonopts, nopts); 12847f6c619Smillert cyclelen = (opt_end - panonopt_start) / ncycle; 12947f6c619Smillert 13047f6c619Smillert for (i = 0; i < ncycle; i++) { 13147f6c619Smillert cstart = panonopt_end+i; 13247f6c619Smillert pos = cstart; 13347f6c619Smillert for (j = 0; j < cyclelen; j++) { 13447f6c619Smillert if (pos >= panonopt_end) 13547f6c619Smillert pos -= nnonopts; 13647f6c619Smillert else 13747f6c619Smillert pos += nopts; 13847f6c619Smillert swap = nargv[pos]; 13947f6c619Smillert /* LINTED const cast */ 14047f6c619Smillert ((char **) nargv)[pos] = nargv[cstart]; 14147f6c619Smillert /* LINTED const cast */ 14247f6c619Smillert ((char **)nargv)[cstart] = swap; 14347f6c619Smillert } 14447f6c619Smillert } 14547f6c619Smillert } 14647f6c619Smillert 14747f6c619Smillert /* 148a4cca5d9Smillert * parse_long_options -- 149a4cca5d9Smillert * Parse long options in argc/argv argument vector. 150a4cca5d9Smillert * Returns -2 if long_only is set and the current option could be a short 151a4cca5d9Smillert * (single character) option instead. 15247f6c619Smillert */ 15347f6c619Smillert static int 154a4cca5d9Smillert parse_long_options(int nargc, char * const *nargv, const char *options, 155a4cca5d9Smillert const struct option *long_options, int *idx, int long_only) 156a4cca5d9Smillert { 157a4cca5d9Smillert char *current_argv, *has_equal; 158a4cca5d9Smillert size_t current_argv_len; 159a4cca5d9Smillert int i, match; 160a4cca5d9Smillert 161a4cca5d9Smillert current_argv = place; 162a4cca5d9Smillert match = -1; 163a4cca5d9Smillert 164a4cca5d9Smillert optind++; 165a4cca5d9Smillert 166a4cca5d9Smillert if ((has_equal = strchr(current_argv, '=')) != NULL) { 167a4cca5d9Smillert /* argument found (--option=arg) */ 168a4cca5d9Smillert current_argv_len = has_equal - current_argv; 169a4cca5d9Smillert has_equal++; 170a4cca5d9Smillert } else 171a4cca5d9Smillert current_argv_len = strlen(current_argv); 172a4cca5d9Smillert 173a4cca5d9Smillert for (i = 0; long_options[i].name; i++) { 174a4cca5d9Smillert /* find matching long option */ 175a4cca5d9Smillert if (strncmp(current_argv, long_options[i].name, 176a4cca5d9Smillert current_argv_len)) 177a4cca5d9Smillert continue; 178a4cca5d9Smillert 179a4cca5d9Smillert if (strlen(long_options[i].name) == current_argv_len) { 180a4cca5d9Smillert /* exact match */ 181a4cca5d9Smillert match = i; 182a4cca5d9Smillert break; 183a4cca5d9Smillert } 184a4cca5d9Smillert /* 185a4cca5d9Smillert * Don't try a partial match of a short option when in 186a4cca5d9Smillert * long_only mode. Otherwise there is a potential conflict 187a4cca5d9Smillert * between partial matches and short options. 188a4cca5d9Smillert */ 189a4cca5d9Smillert if (long_only && current_argv_len == 1) 190a4cca5d9Smillert continue; 191a4cca5d9Smillert 192a4cca5d9Smillert if (match == -1) /* partial match */ 193a4cca5d9Smillert match = i; 194a4cca5d9Smillert else { 195a4cca5d9Smillert /* ambiguous abbreviation */ 196a4cca5d9Smillert if (PRINT_ERROR) 197a4cca5d9Smillert warnx(ambig, (int)current_argv_len, 198a4cca5d9Smillert current_argv); 199a4cca5d9Smillert optopt = 0; 200a4cca5d9Smillert return (BADCH); 201a4cca5d9Smillert } 202a4cca5d9Smillert } 203a4cca5d9Smillert if (match != -1) { /* option found */ 204a4cca5d9Smillert if (long_options[match].has_arg == no_argument 205a4cca5d9Smillert && has_equal) { 206a4cca5d9Smillert if (PRINT_ERROR) 207a4cca5d9Smillert warnx(noarg, (int)current_argv_len, 208a4cca5d9Smillert current_argv); 209a4cca5d9Smillert /* 210a4cca5d9Smillert * XXX: GNU sets optopt to val regardless of flag 211a4cca5d9Smillert */ 212a4cca5d9Smillert if (long_options[match].flag == NULL) 213a4cca5d9Smillert optopt = long_options[match].val; 214a4cca5d9Smillert else 215a4cca5d9Smillert optopt = 0; 216a4cca5d9Smillert return (BADARG); 217a4cca5d9Smillert } 218a4cca5d9Smillert if (long_options[match].has_arg == required_argument || 219a4cca5d9Smillert long_options[match].has_arg == optional_argument) { 220a4cca5d9Smillert if (has_equal) 221a4cca5d9Smillert optarg = has_equal; 222a4cca5d9Smillert else if (long_options[match].has_arg == 223a4cca5d9Smillert required_argument) { 224a4cca5d9Smillert /* 225a4cca5d9Smillert * optional argument doesn't use next nargv 226a4cca5d9Smillert */ 227a4cca5d9Smillert optarg = nargv[optind++]; 228a4cca5d9Smillert } 229a4cca5d9Smillert } 230a4cca5d9Smillert if ((long_options[match].has_arg == required_argument) 231a4cca5d9Smillert && (optarg == NULL)) { 232a4cca5d9Smillert /* 233a4cca5d9Smillert * Missing argument; leading ':' indicates no error 234a4cca5d9Smillert * should be generated. 235a4cca5d9Smillert */ 236a4cca5d9Smillert if (PRINT_ERROR) 237a4cca5d9Smillert warnx(recargstring, 238a4cca5d9Smillert current_argv); 239a4cca5d9Smillert /* 240a4cca5d9Smillert * XXX: GNU sets optopt to val regardless of flag 241a4cca5d9Smillert */ 242a4cca5d9Smillert if (long_options[match].flag == NULL) 243a4cca5d9Smillert optopt = long_options[match].val; 244a4cca5d9Smillert else 245a4cca5d9Smillert optopt = 0; 246a4cca5d9Smillert --optind; 247a4cca5d9Smillert return (BADARG); 248a4cca5d9Smillert } 249a4cca5d9Smillert } else { /* unknown option */ 250a4cca5d9Smillert if (long_only) { 251a4cca5d9Smillert --optind; 252a4cca5d9Smillert return (-2); 253a4cca5d9Smillert } 254a4cca5d9Smillert if (PRINT_ERROR) 255a4cca5d9Smillert warnx(illoptstring, current_argv); 256a4cca5d9Smillert optopt = 0; 257a4cca5d9Smillert return (BADCH); 258a4cca5d9Smillert } 259a4cca5d9Smillert if (idx) 260a4cca5d9Smillert *idx = match; 261a4cca5d9Smillert if (long_options[match].flag) { 262a4cca5d9Smillert *long_options[match].flag = long_options[match].val; 263a4cca5d9Smillert return (0); 264a4cca5d9Smillert } else 265a4cca5d9Smillert return (long_options[match].val); 266a4cca5d9Smillert } 267a4cca5d9Smillert 268a4cca5d9Smillert /* 269a4cca5d9Smillert * getopt_internal -- 270a4cca5d9Smillert * Parse argc/argv argument vector. Called by user level routines. 271a4cca5d9Smillert */ 272a4cca5d9Smillert static int 273a4cca5d9Smillert getopt_internal(int nargc, char * const *nargv, const char *options, 274a4cca5d9Smillert const struct option *long_options, int *idx, int flags) 27547f6c619Smillert { 27647f6c619Smillert char *oli; /* option letter list index */ 27747f6c619Smillert int optchar; 278a4cca5d9Smillert static int posixly_correct = -1; 27947f6c619Smillert 28047f6c619Smillert optarg = NULL; 28147f6c619Smillert 28247f6c619Smillert /* 283a4cca5d9Smillert * Disable GNU extensions if POSIXLY_CORRECT is set or options 284a4cca5d9Smillert * string begins with a '+'. 285a4cca5d9Smillert */ 286a4cca5d9Smillert if (posixly_correct == -1) 287a4cca5d9Smillert posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); 288a4cca5d9Smillert if (posixly_correct || *options == '+') 289a4cca5d9Smillert flags &= ~FLAG_PERMUTE; 290a4cca5d9Smillert else if (*options == '-') 291a4cca5d9Smillert flags |= FLAG_ALLARGS; 292a4cca5d9Smillert if (*options == '+' || *options == '-') 293a4cca5d9Smillert options++; 294a4cca5d9Smillert 295a4cca5d9Smillert /* 29647f6c619Smillert * XXX Some programs (like rsyncd) expect to be able to 29747f6c619Smillert * XXX re-initialize optind to 0 and have getopt_long(3) 29847f6c619Smillert * XXX properly function again. Work around this braindamage. 29947f6c619Smillert */ 30047f6c619Smillert if (optind == 0) 30147f6c619Smillert optind = 1; 30247f6c619Smillert 30347f6c619Smillert if (optreset) 30447f6c619Smillert nonopt_start = nonopt_end = -1; 30547f6c619Smillert start: 30647f6c619Smillert if (optreset || !*place) { /* update scanning pointer */ 30747f6c619Smillert optreset = 0; 30847f6c619Smillert if (optind >= nargc) { /* end of argument vector */ 30947f6c619Smillert place = EMSG; 31047f6c619Smillert if (nonopt_end != -1) { 31147f6c619Smillert /* do permutation, if we have to */ 31247f6c619Smillert permute_args(nonopt_start, nonopt_end, 31347f6c619Smillert optind, nargv); 31447f6c619Smillert optind -= nonopt_end - nonopt_start; 31547f6c619Smillert } 31647f6c619Smillert else if (nonopt_start != -1) { 31747f6c619Smillert /* 31847f6c619Smillert * If we skipped non-options, set optind 31947f6c619Smillert * to the first of them. 32047f6c619Smillert */ 32147f6c619Smillert optind = nonopt_start; 32247f6c619Smillert } 32347f6c619Smillert nonopt_start = nonopt_end = -1; 324a4cca5d9Smillert return (-1); 32547f6c619Smillert } 32647f6c619Smillert if ((*(place = nargv[optind]) != '-') 32747f6c619Smillert || (place[1] == '\0')) { /* found non-option */ 32847f6c619Smillert place = EMSG; 32947f6c619Smillert if (flags & FLAG_ALLARGS) { 33047f6c619Smillert /* 33147f6c619Smillert * GNU extension: 33247f6c619Smillert * return non-option as argument to option 1 33347f6c619Smillert */ 33447f6c619Smillert optarg = nargv[optind++]; 335a4cca5d9Smillert return (INORDER); 33647f6c619Smillert } 33747f6c619Smillert if (!(flags & FLAG_PERMUTE)) { 33847f6c619Smillert /* 33947f6c619Smillert * If no permutation wanted, stop parsing 34047f6c619Smillert * at first non-option. 34147f6c619Smillert */ 342a4cca5d9Smillert return (-1); 34347f6c619Smillert } 34447f6c619Smillert /* do permutation */ 34547f6c619Smillert if (nonopt_start == -1) 34647f6c619Smillert nonopt_start = optind; 34747f6c619Smillert else if (nonopt_end != -1) { 34847f6c619Smillert permute_args(nonopt_start, nonopt_end, 34947f6c619Smillert optind, nargv); 35047f6c619Smillert nonopt_start = optind - 35147f6c619Smillert (nonopt_end - nonopt_start); 35247f6c619Smillert nonopt_end = -1; 35347f6c619Smillert } 35447f6c619Smillert optind++; 35547f6c619Smillert /* process next argument */ 35647f6c619Smillert goto start; 35747f6c619Smillert } 35847f6c619Smillert if (nonopt_start != -1 && nonopt_end == -1) 35947f6c619Smillert nonopt_end = optind; 360a4cca5d9Smillert if (strcmp(place, "--") == 0) { 361a4cca5d9Smillert optind++; 362a4cca5d9Smillert place = EMSG; 363a4cca5d9Smillert /* 364a4cca5d9Smillert * We found an option (--), so if we skipped 365a4cca5d9Smillert * non-options, we have to permute. 366a4cca5d9Smillert */ 367a4cca5d9Smillert if (nonopt_end != -1) { 368a4cca5d9Smillert permute_args(nonopt_start, nonopt_end, 369a4cca5d9Smillert optind, nargv); 370a4cca5d9Smillert optind -= nonopt_end - nonopt_start; 371a4cca5d9Smillert } 372a4cca5d9Smillert nonopt_start = nonopt_end = -1; 373a4cca5d9Smillert return (-1); 374a4cca5d9Smillert } 37547f6c619Smillert place++; 376a4cca5d9Smillert 377a4cca5d9Smillert /* Check long options if we have any */ 378a4cca5d9Smillert if (long_options != NULL) { 379a4cca5d9Smillert int long_only = 0; 380a4cca5d9Smillert 381a4cca5d9Smillert if (*place == '-' || 382a4cca5d9Smillert (long_only = (flags & FLAG_LONGONLY))) { 383a4cca5d9Smillert if (!long_only) 384a4cca5d9Smillert place++; 385a4cca5d9Smillert optchar = parse_long_options(nargc, nargv, 386a4cca5d9Smillert options, long_options, idx, long_only); 387a4cca5d9Smillert if (optchar != -2) { 388a4cca5d9Smillert place = EMSG; 389a4cca5d9Smillert return (optchar); 390a4cca5d9Smillert } 391a4cca5d9Smillert } 39247f6c619Smillert } 39347f6c619Smillert } 39447f6c619Smillert if ((optchar = (int)*place++) == (int)':' || 39547f6c619Smillert (oli = strchr(options, optchar)) == NULL) { 39647f6c619Smillert /* option letter unknown or ':' */ 39747f6c619Smillert if (!*place) 39847f6c619Smillert ++optind; 39947f6c619Smillert if (PRINT_ERROR) 40047f6c619Smillert warnx(illoptchar, optchar); 40147f6c619Smillert optopt = optchar; 402a4cca5d9Smillert return (BADCH); 40347f6c619Smillert } 404a4cca5d9Smillert if (long_options != NULL && optchar == 'W' && oli[1] == ';') { 405a4cca5d9Smillert /* -W long-option */ 406*3106aed5Smillert if (*place) /* no space */ 407*3106aed5Smillert /* NOTHING */; 408*3106aed5Smillert else if (++optind >= nargc) { /* no arg */ 40947f6c619Smillert place = EMSG; 41047f6c619Smillert if (PRINT_ERROR) 41147f6c619Smillert warnx(recargchar, optchar); 41247f6c619Smillert optopt = optchar; 413a4cca5d9Smillert return (BADARG); 41447f6c619Smillert } else /* white space */ 41547f6c619Smillert place = nargv[optind]; 416a4cca5d9Smillert optchar = parse_long_options(nargc, nargv, options, 417a4cca5d9Smillert long_options, idx, 0); 418a4cca5d9Smillert place = EMSG; 419a4cca5d9Smillert return (optchar); 42047f6c619Smillert } 42147f6c619Smillert if (*++oli != ':') { /* doesn't take argument */ 42247f6c619Smillert if (!*place) 42347f6c619Smillert ++optind; 42447f6c619Smillert } else { /* takes (optional) argument */ 42547f6c619Smillert optarg = NULL; 42647f6c619Smillert if (*place) /* no white space */ 42747f6c619Smillert optarg = place; 42847f6c619Smillert /* XXX: disable test for :: if PC? (GNU doesn't) */ 42947f6c619Smillert else if (oli[1] != ':') { /* arg not optional */ 43047f6c619Smillert if (++optind >= nargc) { /* no arg */ 43147f6c619Smillert place = EMSG; 43247f6c619Smillert if (PRINT_ERROR) 43347f6c619Smillert warnx(recargchar, optchar); 43447f6c619Smillert optopt = optchar; 435a4cca5d9Smillert return (BADARG); 43647f6c619Smillert } else 43747f6c619Smillert optarg = nargv[optind]; 43847f6c619Smillert } 43947f6c619Smillert place = EMSG; 44047f6c619Smillert ++optind; 44147f6c619Smillert } 44247f6c619Smillert /* dump back option letter */ 443a4cca5d9Smillert return (optchar); 44447f6c619Smillert } 44547f6c619Smillert 44647f6c619Smillert #ifdef REPLACE_GETOPT 44747f6c619Smillert /* 44847f6c619Smillert * getopt -- 44947f6c619Smillert * Parse argc/argv argument vector. 45047f6c619Smillert * 45147f6c619Smillert * [eventually this will replace the BSD getopt] 45247f6c619Smillert */ 45347f6c619Smillert int 454a4cca5d9Smillert getopt(int nargc, char * const *nargv, const char *options) 45547f6c619Smillert { 45647f6c619Smillert 45747f6c619Smillert /* 458a4cca5d9Smillert * We dont' pass FLAG_PERMUTE to getopt_internal() since 459a4cca5d9Smillert * the BSD getopt(3) (unlike GNU) has never done this. 460a4cca5d9Smillert * 461a4cca5d9Smillert * Furthermore, since many privileged programs call getopt() 462a4cca5d9Smillert * before dropping privileges it makes sense to keep things 463a4cca5d9Smillert * as simple (and bug-free) as possible. 46447f6c619Smillert */ 465a4cca5d9Smillert return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); 46647f6c619Smillert } 46747f6c619Smillert #endif /* REPLACE_GETOPT */ 46847f6c619Smillert 46947f6c619Smillert /* 47047f6c619Smillert * getopt_long -- 47147f6c619Smillert * Parse argc/argv argument vector. 47247f6c619Smillert */ 47347f6c619Smillert int 47447f6c619Smillert getopt_long(nargc, nargv, options, long_options, idx) 47547f6c619Smillert int nargc; 47647f6c619Smillert char * const *nargv; 47747f6c619Smillert const char *options; 47847f6c619Smillert const struct option *long_options; 47947f6c619Smillert int *idx; 48047f6c619Smillert { 48147f6c619Smillert 482a4cca5d9Smillert return (getopt_internal(nargc, nargv, options, long_options, idx, 483a4cca5d9Smillert FLAG_PERMUTE)); 48447f6c619Smillert } 48547f6c619Smillert 48647f6c619Smillert /* 48747f6c619Smillert * getopt_long_only -- 48847f6c619Smillert * Parse argc/argv argument vector. 48947f6c619Smillert */ 49047f6c619Smillert int 49147f6c619Smillert getopt_long_only(nargc, nargv, options, long_options, idx) 49247f6c619Smillert int nargc; 49347f6c619Smillert char * const *nargv; 49447f6c619Smillert const char *options; 49547f6c619Smillert const struct option *long_options; 49647f6c619Smillert int *idx; 49747f6c619Smillert { 49847f6c619Smillert 499a4cca5d9Smillert return (getopt_internal(nargc, nargv, options, long_options, idx, 500a4cca5d9Smillert FLAG_PERMUTE|FLAG_LONGONLY)); 50147f6c619Smillert } 502