xref: /illumos-gate/usr/src/lib/libc/port/gen/getopt.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
29*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * See getopt(3C) and SUS/XPG getopt() for function definition and
34*7c478bd9Sstevel@tonic-gate  * requirements.
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * This actual implementation is a bit looser than the specification
37*7c478bd9Sstevel@tonic-gate  * as it allows any character other than ':' and '(' to be used as
38*7c478bd9Sstevel@tonic-gate  * a short option character - The specification only guarantees the
39*7c478bd9Sstevel@tonic-gate  * alnum characters ([a-z][A-Z][0-9]).
40*7c478bd9Sstevel@tonic-gate  */
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #pragma weak getopt = _getopt
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include "synonyms.h"
45*7c478bd9Sstevel@tonic-gate #include "_libc_gettext.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include <unistd.h>
48*7c478bd9Sstevel@tonic-gate #include <string.h>
49*7c478bd9Sstevel@tonic-gate #include <stdio.h>
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  * Generalized error processing macro. The parameter i is a pointer to
53*7c478bd9Sstevel@tonic-gate  * the failed option string. If it is NULL, the character in c is converted
54*7c478bd9Sstevel@tonic-gate  * to a string and displayed instead. s is the error text.
55*7c478bd9Sstevel@tonic-gate  *
56*7c478bd9Sstevel@tonic-gate  * This could be / should be a static function if it is used more, but
57*7c478bd9Sstevel@tonic-gate  * that would require moving the 'optstring[0]' test outside of the
58*7c478bd9Sstevel@tonic-gate  * function.
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate #define	ERR(s, c, i)	if (opterr && optstring[0] != ':') { \
61*7c478bd9Sstevel@tonic-gate 	char errbuf[256]; \
62*7c478bd9Sstevel@tonic-gate 	char cbuf[2]; \
63*7c478bd9Sstevel@tonic-gate 	cbuf[0] = c; \
64*7c478bd9Sstevel@tonic-gate 	cbuf[1] = '\0'; \
65*7c478bd9Sstevel@tonic-gate 	(void) snprintf(errbuf, sizeof (errbuf), s, argv[0], \
66*7c478bd9Sstevel@tonic-gate 	    (i ? argv[i]+2 : cbuf)); \
67*7c478bd9Sstevel@tonic-gate 	(void) write(2, errbuf, strlen(errbuf)); }
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*
70*7c478bd9Sstevel@tonic-gate  * _sp is required to keep state between successive calls to getopt() while
71*7c478bd9Sstevel@tonic-gate  * extracting aggregated short-options (ie: -abcd). Hence, getopt() is not
72*7c478bd9Sstevel@tonic-gate  * thread safe or reentrant, but it really doesn't matter.
73*7c478bd9Sstevel@tonic-gate  *
74*7c478bd9Sstevel@tonic-gate  * So, why isn't this "static" you ask?  Because the historical Bourne
75*7c478bd9Sstevel@tonic-gate  * shell has actually latched on to this little piece of private data.
76*7c478bd9Sstevel@tonic-gate  */
77*7c478bd9Sstevel@tonic-gate int _sp = 1;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /*
80*7c478bd9Sstevel@tonic-gate  * Determine if the specified character (c) is present in the string
81*7c478bd9Sstevel@tonic-gate  * (optstring) as a regular, single character option. If the option is found,
82*7c478bd9Sstevel@tonic-gate  * return a pointer into optstring pointing at the short-option character,
83*7c478bd9Sstevel@tonic-gate  * otherwise return null. The characters ':' and '(' are not allowed.
84*7c478bd9Sstevel@tonic-gate  */
85*7c478bd9Sstevel@tonic-gate static char *
86*7c478bd9Sstevel@tonic-gate parseshort(const char *optstring, const char c)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	char *cp = (char *)optstring;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	if (c == ':' || c == '(')
91*7c478bd9Sstevel@tonic-gate 		return (NULL);
92*7c478bd9Sstevel@tonic-gate 	do {
93*7c478bd9Sstevel@tonic-gate 		if (*cp == c)
94*7c478bd9Sstevel@tonic-gate 			return (cp);
95*7c478bd9Sstevel@tonic-gate 		while (*cp == '(')
96*7c478bd9Sstevel@tonic-gate 			while (*cp != '\0' && *cp != ')')
97*7c478bd9Sstevel@tonic-gate 				cp++;
98*7c478bd9Sstevel@tonic-gate 	} while (*cp++ != '\0');
99*7c478bd9Sstevel@tonic-gate 	return (NULL);
100*7c478bd9Sstevel@tonic-gate }
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate /*
103*7c478bd9Sstevel@tonic-gate  * Determine if the specified string (opt) is present in the string
104*7c478bd9Sstevel@tonic-gate  * (optstring) as a long-option contained within parenthesis. If the
105*7c478bd9Sstevel@tonic-gate  * long-option specifies option-argument, return a pointer to it in
106*7c478bd9Sstevel@tonic-gate  * longoptarg.  Otherwise set longoptarg to null. If the option is found,
107*7c478bd9Sstevel@tonic-gate  * return a pointer into optstring pointing at the short-option character
108*7c478bd9Sstevel@tonic-gate  * associated with this long-option; otherwise return null.
109*7c478bd9Sstevel@tonic-gate  *
110*7c478bd9Sstevel@tonic-gate  * optstring 	The entire optstring passed to getopt() by the caller
111*7c478bd9Sstevel@tonic-gate  *
112*7c478bd9Sstevel@tonic-gate  * opt		The long option read from the command line
113*7c478bd9Sstevel@tonic-gate  *
114*7c478bd9Sstevel@tonic-gate  * longoptarg	The argument to the option is returned in this parameter,
115*7c478bd9Sstevel@tonic-gate  *              if an option exists. Possible return values in longoptarg
116*7c478bd9Sstevel@tonic-gate  *              are:
117*7c478bd9Sstevel@tonic-gate  *                  NULL		No argument was found
118*7c478bd9Sstevel@tonic-gate  *		    empty string ("")	Argument was explicitly left empty
119*7c478bd9Sstevel@tonic-gate  *					by the user (e.g., --option= )
120*7c478bd9Sstevel@tonic-gate  *		    valid string	Argument found on the command line
121*7c478bd9Sstevel@tonic-gate  *
122*7c478bd9Sstevel@tonic-gate  * returns	Pointer to equivalent short-option in optstring, null
123*7c478bd9Sstevel@tonic-gate  *              if option not found in optstring.
124*7c478bd9Sstevel@tonic-gate  *
125*7c478bd9Sstevel@tonic-gate  * ASSUMES: No parameters are NULL
126*7c478bd9Sstevel@tonic-gate  *
127*7c478bd9Sstevel@tonic-gate  */
128*7c478bd9Sstevel@tonic-gate static char *
129*7c478bd9Sstevel@tonic-gate parselong(const char *optstring, const char *opt, char **longoptarg)
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	char	*cp;	/* ptr into optstring, beginning of one option spec. */
132*7c478bd9Sstevel@tonic-gate 	char	*ip;	/* ptr into optstring, traverses every char */
133*7c478bd9Sstevel@tonic-gate 	char	*op;	/* pointer into opt */
134*7c478bd9Sstevel@tonic-gate 	int	match;	/* nonzero if opt is matching part of optstring */
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	cp = ip = (char *)optstring;
137*7c478bd9Sstevel@tonic-gate 	do {
138*7c478bd9Sstevel@tonic-gate 		if (*ip != '(' && *++ip == '\0')
139*7c478bd9Sstevel@tonic-gate 			break;
140*7c478bd9Sstevel@tonic-gate 		if (*ip == ':' && *++ip == '\0')
141*7c478bd9Sstevel@tonic-gate 			break;
142*7c478bd9Sstevel@tonic-gate 		while (*ip == '(') {
143*7c478bd9Sstevel@tonic-gate 			if (*++ip == '\0')
144*7c478bd9Sstevel@tonic-gate 				break;
145*7c478bd9Sstevel@tonic-gate 			op = (char *)opt;
146*7c478bd9Sstevel@tonic-gate 			match = 1;
147*7c478bd9Sstevel@tonic-gate 			while (*ip != ')' && *ip != '\0' && *op != '\0')
148*7c478bd9Sstevel@tonic-gate 				match = (*ip++ == *op++ && match);
149*7c478bd9Sstevel@tonic-gate 			if (match && *ip == ')' &&
150*7c478bd9Sstevel@tonic-gate 			    (*op == '\0' || *op == '=')) {
151*7c478bd9Sstevel@tonic-gate 				if ((*op) == '=') {
152*7c478bd9Sstevel@tonic-gate 				    /* may be an empty string - OK */
153*7c478bd9Sstevel@tonic-gate 				    (*longoptarg) = op + 1;
154*7c478bd9Sstevel@tonic-gate 				} else {
155*7c478bd9Sstevel@tonic-gate 				    (*longoptarg) = NULL;
156*7c478bd9Sstevel@tonic-gate 				}
157*7c478bd9Sstevel@tonic-gate 				return (cp);
158*7c478bd9Sstevel@tonic-gate 			}
159*7c478bd9Sstevel@tonic-gate 			if (*ip == ')' && *++ip == '\0')
160*7c478bd9Sstevel@tonic-gate 				break;
161*7c478bd9Sstevel@tonic-gate 		}
162*7c478bd9Sstevel@tonic-gate 		cp = ip;
163*7c478bd9Sstevel@tonic-gate 		/*
164*7c478bd9Sstevel@tonic-gate 		 * Handle double-colon in optstring ("a::(longa)")
165*7c478bd9Sstevel@tonic-gate 		 * The old getopt() accepts it and treats it as a
166*7c478bd9Sstevel@tonic-gate 		 * required argument.
167*7c478bd9Sstevel@tonic-gate 		 */
168*7c478bd9Sstevel@tonic-gate 		while ((cp > optstring) && ((*cp) == ':')) {
169*7c478bd9Sstevel@tonic-gate 		    --cp;
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 	} while (*cp != '\0');
172*7c478bd9Sstevel@tonic-gate 	return (NULL);
173*7c478bd9Sstevel@tonic-gate } /* parselong() */
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate /*
176*7c478bd9Sstevel@tonic-gate  * External function entry point.
177*7c478bd9Sstevel@tonic-gate  */
178*7c478bd9Sstevel@tonic-gate int
179*7c478bd9Sstevel@tonic-gate getopt(int argc, char *const *argv, const char *optstring)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	char	c;
182*7c478bd9Sstevel@tonic-gate 	char	*cp;
183*7c478bd9Sstevel@tonic-gate 	int	longopt;
184*7c478bd9Sstevel@tonic-gate 	char	*longoptarg;
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	/*
187*7c478bd9Sstevel@tonic-gate 	 * Has the end of the options been encountered?  The following
188*7c478bd9Sstevel@tonic-gate 	 * implements the SUS requirements:
189*7c478bd9Sstevel@tonic-gate 	 *
190*7c478bd9Sstevel@tonic-gate 	 * If, when getopt() is called:
191*7c478bd9Sstevel@tonic-gate 	 *	argv[optind]	is a null pointer
192*7c478bd9Sstevel@tonic-gate 	 *	*argv[optind]	is not the character '-'
193*7c478bd9Sstevel@tonic-gate 	 *	argv[optind]	points to the string "-"
194*7c478bd9Sstevel@tonic-gate 	 * getopt() returns -1 without changing optind. If
195*7c478bd9Sstevel@tonic-gate 	 *	argv[optind]	points to the string "--"
196*7c478bd9Sstevel@tonic-gate 	 * getopt() returns -1 after incrementing optind.
197*7c478bd9Sstevel@tonic-gate 	 */
198*7c478bd9Sstevel@tonic-gate 	if (_sp == 1) {
199*7c478bd9Sstevel@tonic-gate 		if (optind >= argc || argv[optind][0] != '-' ||
200*7c478bd9Sstevel@tonic-gate 		    argv[optind] == NULL || argv[optind][1] == '\0')
201*7c478bd9Sstevel@tonic-gate 			return (EOF);
202*7c478bd9Sstevel@tonic-gate 		else if (strcmp(argv[optind], "--") == NULL) {
203*7c478bd9Sstevel@tonic-gate 			optind++;
204*7c478bd9Sstevel@tonic-gate 			return (EOF);
205*7c478bd9Sstevel@tonic-gate 		}
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	/*
209*7c478bd9Sstevel@tonic-gate 	 * Getting this far indicates that an option has been encountered.
210*7c478bd9Sstevel@tonic-gate 	 * Note that the syntax of optstring applies special meanings to
211*7c478bd9Sstevel@tonic-gate 	 * the characters ':' and '(', so they are not permissible as
212*7c478bd9Sstevel@tonic-gate 	 * option letters. A special meaning is also applied to the ')'
213*7c478bd9Sstevel@tonic-gate 	 * character, but its meaning can be determined from context.
214*7c478bd9Sstevel@tonic-gate 	 * Note that the specification only requires that the alnum
215*7c478bd9Sstevel@tonic-gate 	 * characters be accepted.
216*7c478bd9Sstevel@tonic-gate 	 *
217*7c478bd9Sstevel@tonic-gate 	 * If the second character of the argument is a '-' this must be
218*7c478bd9Sstevel@tonic-gate 	 * a long-option, otherwise it must be a short option.  Scan for
219*7c478bd9Sstevel@tonic-gate 	 * the option in optstring by the appropriate algorithm. Either
220*7c478bd9Sstevel@tonic-gate 	 * scan will return a pointer to the short-option character in
221*7c478bd9Sstevel@tonic-gate 	 * optstring if the option is found and NULL otherwise.
222*7c478bd9Sstevel@tonic-gate 	 *
223*7c478bd9Sstevel@tonic-gate 	 * For an unrecognized long-option, optopt will equal 0, but
224*7c478bd9Sstevel@tonic-gate 	 * since long-options can't aggregate the failing option can
225*7c478bd9Sstevel@tonic-gate 	 * be identified by argv[optind-1].
226*7c478bd9Sstevel@tonic-gate 	 */
227*7c478bd9Sstevel@tonic-gate 	optopt = c = (unsigned char)argv[optind][_sp];
228*7c478bd9Sstevel@tonic-gate 	optarg = NULL;
229*7c478bd9Sstevel@tonic-gate 	longopt = (_sp == 1 && c == '-');
230*7c478bd9Sstevel@tonic-gate 	if (!(longopt ?
231*7c478bd9Sstevel@tonic-gate 	    ((cp = parselong(optstring, argv[optind]+2, &longoptarg)) != NULL) :
232*7c478bd9Sstevel@tonic-gate 	    ((cp = parseshort(optstring, c)) != NULL))) {
233*7c478bd9Sstevel@tonic-gate 		/* LINTED: variable format specifier */
234*7c478bd9Sstevel@tonic-gate 		ERR(_libc_gettext("%s: illegal option -- %s\n"),
235*7c478bd9Sstevel@tonic-gate 		    c, (longopt ? optind : 0));
236*7c478bd9Sstevel@tonic-gate 		/*
237*7c478bd9Sstevel@tonic-gate 		 * Note: When the long option is unrecognized, optopt
238*7c478bd9Sstevel@tonic-gate 		 * will be '-' here, which matches the specification.
239*7c478bd9Sstevel@tonic-gate 		 */
240*7c478bd9Sstevel@tonic-gate 		if (argv[optind][++_sp] == '\0' || longopt) {
241*7c478bd9Sstevel@tonic-gate 			optind++;
242*7c478bd9Sstevel@tonic-gate 			_sp = 1;
243*7c478bd9Sstevel@tonic-gate 		}
244*7c478bd9Sstevel@tonic-gate 		return ('?');
245*7c478bd9Sstevel@tonic-gate 	}
246*7c478bd9Sstevel@tonic-gate 	optopt = c = *cp;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	/*
249*7c478bd9Sstevel@tonic-gate 	 * A valid option has been identified.  If it should have an
250*7c478bd9Sstevel@tonic-gate 	 * option-argument, process that now.  SUS defines the setting
251*7c478bd9Sstevel@tonic-gate 	 * of optarg as follows:
252*7c478bd9Sstevel@tonic-gate 	 *
253*7c478bd9Sstevel@tonic-gate 	 *   1.	If the option was the last character in the string pointed to
254*7c478bd9Sstevel@tonic-gate 	 *	by an element of argv, then optarg contains the next element
255*7c478bd9Sstevel@tonic-gate 	 *	of argv, and optind is incremented by 2. If the resulting
256*7c478bd9Sstevel@tonic-gate 	 *	value of optind is not less than argc, this indicates a
257*7c478bd9Sstevel@tonic-gate 	 *	missing option-argument, and getopt() returns an error
258*7c478bd9Sstevel@tonic-gate 	 *	indication.
259*7c478bd9Sstevel@tonic-gate 	 *
260*7c478bd9Sstevel@tonic-gate 	 *   2.	Otherwise, optarg points to the string following the option
261*7c478bd9Sstevel@tonic-gate 	 *	character in that element of argv, and optind is incremented
262*7c478bd9Sstevel@tonic-gate 	 *	by 1.
263*7c478bd9Sstevel@tonic-gate 	 *
264*7c478bd9Sstevel@tonic-gate 	 * The second clause allows -abcd (where b requires an option-argument)
265*7c478bd9Sstevel@tonic-gate 	 * to be interpreted as "-a -b cd".
266*7c478bd9Sstevel@tonic-gate 	 *
267*7c478bd9Sstevel@tonic-gate 	 * Note that the option-argument can legally be an empty string,
268*7c478bd9Sstevel@tonic-gate 	 * such as:
269*7c478bd9Sstevel@tonic-gate 	 * 	command --option= operand
270*7c478bd9Sstevel@tonic-gate 	 * which explicitly sets the value of --option to nil
271*7c478bd9Sstevel@tonic-gate 	 */
272*7c478bd9Sstevel@tonic-gate 	if (*(cp + 1) == ':') {
273*7c478bd9Sstevel@tonic-gate 		/* The option takes an argument */
274*7c478bd9Sstevel@tonic-gate 		if (!longopt && argv[optind][_sp+1] != '\0') {
275*7c478bd9Sstevel@tonic-gate 			optarg = &argv[optind++][_sp+1];
276*7c478bd9Sstevel@tonic-gate 		} else if (longopt && longoptarg) {
277*7c478bd9Sstevel@tonic-gate 			/*
278*7c478bd9Sstevel@tonic-gate 			 * The option argument was explicitly set to
279*7c478bd9Sstevel@tonic-gate 			 * the empty string on the command line (--option=)
280*7c478bd9Sstevel@tonic-gate 			 */
281*7c478bd9Sstevel@tonic-gate 			optind++;
282*7c478bd9Sstevel@tonic-gate 			optarg = longoptarg;
283*7c478bd9Sstevel@tonic-gate 		} else if (++optind >= argc) {
284*7c478bd9Sstevel@tonic-gate 			/* LINTED: variable format specifier */
285*7c478bd9Sstevel@tonic-gate 			ERR(_libc_gettext("%s: option requires an argument" \
286*7c478bd9Sstevel@tonic-gate 			    " -- %s\n"), c, (longopt ? optind - 1 : 0));
287*7c478bd9Sstevel@tonic-gate 			_sp = 1;
288*7c478bd9Sstevel@tonic-gate 			optarg = NULL;
289*7c478bd9Sstevel@tonic-gate 			return (optstring[0] == ':' ? ':' : '?');
290*7c478bd9Sstevel@tonic-gate 		} else
291*7c478bd9Sstevel@tonic-gate 			optarg = argv[optind++];
292*7c478bd9Sstevel@tonic-gate 		_sp = 1;
293*7c478bd9Sstevel@tonic-gate 	} else {
294*7c478bd9Sstevel@tonic-gate 		/* The option does NOT take an argument */
295*7c478bd9Sstevel@tonic-gate 		if (longopt && (longoptarg != NULL)) {
296*7c478bd9Sstevel@tonic-gate 		    /* User supplied an arg to an option that takes none */
297*7c478bd9Sstevel@tonic-gate 		    /* LINTED: variable format specifier */
298*7c478bd9Sstevel@tonic-gate 		    ERR(_libc_gettext(
299*7c478bd9Sstevel@tonic-gate 			"%s: option doesn't take an argument -- %s\n"),
300*7c478bd9Sstevel@tonic-gate 			0, (longopt ? optind : 0));
301*7c478bd9Sstevel@tonic-gate 		    optarg = longoptarg = NULL;
302*7c478bd9Sstevel@tonic-gate 		    c = '?';
303*7c478bd9Sstevel@tonic-gate 		}
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 		if (longopt || argv[optind][++_sp] == '\0') {
306*7c478bd9Sstevel@tonic-gate 			_sp = 1;
307*7c478bd9Sstevel@tonic-gate 			optind++;
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 		optarg = NULL;
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 	return (c);
312*7c478bd9Sstevel@tonic-gate } /* getopt() */
313