1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*	$OpenBSD: getopt_long.c,v 1.24 2010/07/22 19:31:53 blambert Exp $	*/
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*	$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $	*/
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission to use, copy, modify, and distribute this software for any
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * purpose with or without fee is hereby granted, provided that the above
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copyright notice and this permission notice appear in all copies.
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Sponsored in part by the Defense Advanced Research Projects
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Agency (DARPA) and Air Force Research Laboratory, Air Force
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*-
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (c) 2000 The NetBSD Foundation, Inc.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All rights reserved.
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This code is derived from software contributed to The NetBSD Foundation
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * by Dieter Baron and Thomas Klausner.
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Redistribution and use in source and binary forms, with or without
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * modification, are permitted provided that the following conditions
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * are met:
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1. Redistributions of source code must retain the above copyright
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    notice, this list of conditions and the following disclaimer.
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    notice, this list of conditions and the following disclaimer in the
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    documentation and/or other materials provided with the distribution.
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * POSSIBILITY OF SUCH DAMAGE.
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <errno.h>
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <getopt.h>
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h>
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string.h>
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint	opterr = 1;		/* if error message should be printed */
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint	optind = 1;		/* index into parent argv vector */
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint	optopt = '?';		/* character checked for validity */
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint	optreset;		/* reset getopt */
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgchar    *optarg;		/* argument associated with option */
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_ERROR	((opterr) && (*options != ':'))
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* return values */
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define	BADCH		(int)'?'
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define	INORDER 	(int)1
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define	EMSG		""
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int getopt_internal(int, char * const *, const char *,
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   const struct option *, int *, int);
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int parse_long_options(char * const *, const char *,
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			      const struct option *, int *, int);
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int gcd(int, int);
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void permute_args(int, int, int, char * const *);
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic char *place = EMSG; /* option letter processing */
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* XXX: set optreset to 1 rather than these two */
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int nonopt_start = -1; /* first non option argument (for permute) */
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int nonopt_end = -1;   /* first option after non options (for permute) */
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Error messages */
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char recargchar[] = "option requires an argument -- %c";
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char recargstring[] = "option requires an argument -- %s";
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char ambig[] = "ambiguous option -- %.*s";
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char noarg[] = "option doesn't take an argument -- %.*s";
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char illoptchar[] = "unknown option -- %c";
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char illoptstring[] = "unknown option -- %s";
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Compute the greatest common divisor of a and b.
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggcd(int a, int b)
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int c;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c = a % b;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (c != 0) {
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		a = b;
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		b = c;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		c = a % b;
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (b);
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Exchange the block from nonopt_start to nonopt_end with the block
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * from nonopt_end to opt_end (keeping the same order of arguments
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in each block).
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpermute_args(int panonopt_start, int panonopt_end, int opt_end,
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char * const *nargv)
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *swap;
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * compute lengths of blocks and number and size of cycles
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	nnonopts = panonopt_end - panonopt_start;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	nopts = opt_end - panonopt_end;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	ncycle = gcd(nnonopts, nopts);
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	cyclelen = (opt_end - panonopt_start) / ncycle;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (i = 0; i < ncycle; i++) {
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		cstart = panonopt_end+i;
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		pos = cstart;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (j = 0; j < cyclelen; j++) {
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (pos >= panonopt_end)
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				pos -= nnonopts;
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				pos += nopts;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			swap = nargv[pos];
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* LINTED const cast */
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			((char **) nargv)[pos] = nargv[cstart];
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* LINTED const cast */
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			((char **)nargv)[cstart] = swap;
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * parse_long_options --
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *	Parse long options in argc/argv argument vector.
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns -1 if short_too is set and the option does not match long_options.
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgparse_long_options(char * const *nargv, const char *options,
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct option *long_options, int *idx, int short_too)
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *current_argv, *has_equal;
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	size_t current_argv_len;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int i, match;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	current_argv = place;
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	match = -1;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	optind++;
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((has_equal = strchr(current_argv, '=')) != NULL) {
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* argument found (--option=arg) */
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		current_argv_len = has_equal - current_argv;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		has_equal++;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		current_argv_len = strlen(current_argv);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (i = 0; long_options[i].name; i++) {
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* find matching long option */
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (strncmp(current_argv, long_options[i].name,
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    current_argv_len))
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (strlen(long_options[i].name) == current_argv_len) {
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* exact match */
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			match = i;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * If this is a known short option, don't allow
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * a partial match of a single character.
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (short_too && current_argv_len == 1)
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (match == -1)	/* partial match */
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			match = i;
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else {
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* ambiguous abbreviation */
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (PRINT_ERROR)
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, ambig, (int)current_argv_len,
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				     current_argv);
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			optopt = 0;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (BADCH);
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (match != -1) {		/* option found */
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (long_options[match].has_arg == no_argument
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    && has_equal) {
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (PRINT_ERROR)
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, noarg, (int)current_argv_len,
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				     current_argv);
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * XXX: GNU sets optopt to val regardless of flag
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (long_options[match].flag == NULL)
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optopt = long_options[match].val;
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optopt = 0;
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (BADARG);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (long_options[match].has_arg == required_argument ||
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    long_options[match].has_arg == optional_argument) {
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (has_equal)
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optarg = has_equal;
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if (long_options[match].has_arg ==
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    required_argument) {
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * optional argument doesn't use next nargv
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optarg = nargv[optind++];
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if ((long_options[match].has_arg == required_argument)
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    && (optarg == NULL)) {
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * Missing argument; leading ':' indicates no error
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * should be generated.
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (PRINT_ERROR)
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, recargstring,
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    current_argv);
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * XXX: GNU sets optopt to val regardless of flag
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (long_options[match].flag == NULL)
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optopt = long_options[match].val;
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optopt = 0;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			--optind;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (BADARG);
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {			/* unknown option */
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (short_too) {
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			--optind;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (-1);
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (PRINT_ERROR)
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			fprintf(stderr, illoptstring, current_argv);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optopt = 0;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (BADCH);
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (idx)
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*idx = match;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (long_options[match].flag) {
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*long_options[match].flag = long_options[match].val;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (0);
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (long_options[match].val);
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * getopt_internal --
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *	Parse argc/argv argument vector.  Called by user level routines.
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetopt_internal(int nargc, char * const *nargv, const char *options,
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct option *long_options, int *idx, int flags)
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *oli;				/* option letter list index */
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int optchar, short_too;
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	static int posixly_correct = -1;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (options == NULL)
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (-1);
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * string begins with a '+'.
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (posixly_correct == -1)
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (posixly_correct || *options == '+')
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		flags &= ~FLAG_PERMUTE;
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (*options == '-')
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		flags |= FLAG_ALLARGS;
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (*options == '+' || *options == '-')
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		options++;
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * XXX using optreset.  Work around this braindamage.
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (optind == 0)
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optind = optreset = 1;
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	optarg = NULL;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (optreset)
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		nonopt_start = nonopt_end = -1;
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstart:
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (optreset || !*place) {		/* update scanning pointer */
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optreset = 0;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (optind >= nargc) {          /* end of argument vector */
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = EMSG;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (nonopt_end != -1) {
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* do permutation, if we have to */
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				permute_args(nonopt_start, nonopt_end,
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    optind, nargv);
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optind -= nonopt_end - nonopt_start;
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if (nonopt_start != -1) {
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * If we skipped non-options, set optind
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * to the first of them.
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optind = nonopt_start;
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			nonopt_start = nonopt_end = -1;
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (-1);
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (*(place = nargv[optind]) != '-' ||
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = EMSG;		/* found non-option */
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (flags & FLAG_ALLARGS) {
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * GNU extension:
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * return non-option as argument to option 1
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optarg = nargv[optind++];
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return (INORDER);
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (!(flags & FLAG_PERMUTE)) {
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * If no permutation wanted, stop parsing
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * at first non-option.
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return (-1);
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* do permutation */
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (nonopt_start == -1)
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				nonopt_start = optind;
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if (nonopt_end != -1) {
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				permute_args(nonopt_start, nonopt_end,
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    optind, nargv);
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				nonopt_start = optind -
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    (nonopt_end - nonopt_start);
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				nonopt_end = -1;
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			optind++;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* process next argument */
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			goto start;
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (nonopt_start != -1 && nonopt_end == -1)
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			nonopt_end = optind;
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * If we have "-" do nothing, if "--" we are done.
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			optind++;
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = EMSG;
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * We found an option (--), so if we skipped
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * non-options, we have to permute.
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (nonopt_end != -1) {
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				permute_args(nonopt_start, nonopt_end,
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    optind, nargv);
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optind -= nonopt_end - nonopt_start;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			nonopt_start = nonopt_end = -1;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (-1);
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Check long options if:
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *  1) we were passed some
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *  2) the arg is not just "-"
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *  3) either the arg starts with -- we are getopt_long_only()
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (long_options != NULL && place != nargv[optind] &&
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    (*place == '-' || (flags & FLAG_LONGONLY))) {
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		short_too = 0;
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (*place == '-')
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place++;		/* --foo long option */
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (*place != ':' && strchr(options, *place) != NULL)
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			short_too = 1;		/* could be short option too */
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optchar = parse_long_options(nargv, options, long_options,
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    idx, short_too);
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (optchar != -1) {
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = EMSG;
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (optchar);
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((optchar = (int)*place++) == (int)':' ||
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    (optchar == (int)'-' && *place != '\0') ||
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    (oli = strchr(options, optchar)) == NULL) {
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * If the user specified "-" and  '-' isn't listed in
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * options, return -1 (non-option) as per POSIX.
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * Otherwise, it is an unknown option character (or ':').
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (optchar == (int)'-' && *place == '\0')
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (-1);
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (!*place)
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			++optind;
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (PRINT_ERROR)
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			fprintf(stderr, illoptchar, optchar);
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optopt = optchar;
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (BADCH);
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* -W long-option */
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (*place)			/* no space */
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* NOTHING */;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (++optind >= nargc) {	/* no arg */
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = EMSG;
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (PRINT_ERROR)
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, recargchar, optchar);
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			optopt = optchar;
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return (BADARG);
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else				/* white space */
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			place = nargv[optind];
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optchar = parse_long_options(nargv, options, long_options,
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    idx, 0);
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		place = EMSG;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return (optchar);
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (*++oli != ':') {			/* doesn't take argument */
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (!*place)
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			++optind;
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {				/* takes (optional) argument */
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		optarg = NULL;
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (*place)			/* no white space */
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			optarg = place;
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (oli[1] != ':') {	/* arg not optional */
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (++optind >= nargc) {	/* no arg */
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				place = EMSG;
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (PRINT_ERROR)
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fprintf(stderr, recargchar, optchar);
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optopt = optchar;
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return (BADARG);
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				optarg = nargv[optind];
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		place = EMSG;
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		++optind;
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* dump back option letter */
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (optchar);
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * getopt --
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *	Parse argc/argv argument vector.
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * [eventually this will replace the BSD getopt]
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetopt(int nargc, char * const *nargv, const char *options)
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * We don't pass FLAG_PERMUTE to getopt_internal() since
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * the BSD getopt(3) (unlike GNU) has never done this.
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Furthermore, since many privileged programs call getopt()
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * before dropping privileges it makes sense to keep things
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * as simple (and bug-free) as possible.
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * getopt_long --
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *	Parse argc/argv argument vector.
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetopt_long(int nargc, char * const *nargv, const char *options,
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const struct option *long_options, int *idx)
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (getopt_internal(nargc, nargv, options, long_options, idx,
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    FLAG_PERMUTE));
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * getopt_long_only --
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *	Parse argc/argv argument vector.
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetopt_long_only(int nargc, char * const *nargv, const char *options,
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const struct option *long_options, int *idx)
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (getopt_internal(nargc, nargv, options, long_options, idx,
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    FLAG_PERMUTE|FLAG_LONGONLY));
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
512