4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
32 * See getopt(3C) and SUS/XPG getopt() for function definition and
35 * This actual implementation is a bit looser than the specification
36 * as it allows any character other than ':' and '(' to be used as
37 * a short option character - The specification only guarantees the
38 * alnum characters ([a-z][A-Z][0-9]).
41 #pragma weak _getopt = getopt
44 #include "_libc_gettext.h"
51 * Generalized error processing macro. The parameter i is a pointer to
52 * the failed option string. If it is NULL, the character in c is converted
53 * to a string and displayed instead. s is the error text.
55 * This could be / should be a static function if it is used more, but
56 * that would require moving the 'optstring[0]' test outside of the
59 #define ERR(s, c, i) if (opterr && optstring[0] != ':') { \
64 (void) snprintf(errbuf, sizeof (errbuf), s, argv[0], \
65 (i ? argv[i]+2 : cbuf)); \
66 (void) write(2, errbuf, strlen(errbuf)); }
69 * _sp is required to keep state between successive calls to getopt() while
70 * extracting aggregated short-options (ie: -abcd). Hence, getopt() is not
71 * thread safe or reentrant, but it really doesn't matter.
73 * So, why isn't this "static" you ask? Because the historical Bourne
74 * shell has actually latched on to this little piece of private data.
79 * Determine if the specified character (c) is present in the string
80 * (optstring) as a regular, single character option. If the option is found,
81 * return a pointer into optstring pointing at the short-option character,
82 * otherwise return null. The characters ':' and '(' are not allowed.
85 parseshort(const char *optstring
, const char c
)
87 char *cp
= (char *)optstring
;
89 if (c
== ':' || c
== '(')
95 while (*cp
!= '\0' && *cp
!= ')')
97 } while (*cp
++ != '\0');
102 * Determine if the specified string (opt) is present in the string
103 * (optstring) as a long-option contained within parenthesis. If the
104 * long-option specifies option-argument, return a pointer to it in
105 * longoptarg. Otherwise set longoptarg to null. If the option is found,
106 * return a pointer into optstring pointing at the short-option character
107 * associated with this long-option; otherwise return null.
109 * optstring The entire optstring passed to getopt() by the caller
111 * opt The long option read from the command line
113 * longoptarg The argument to the option is returned in this parameter,
114 * if an option exists. Possible return values in longoptarg
116 * NULL No argument was found
117 * empty string ("") Argument was explicitly left empty
118 * by the user (e.g., --option= )
119 * valid string Argument found on the command line
121 * returns Pointer to equivalent short-option in optstring, null
122 * if option not found in optstring.
124 * ASSUMES: No parameters are NULL
128 parselong(const char *optstring
, const char *opt
, char **longoptarg
)
130 char *cp
; /* ptr into optstring, beginning of one option spec. */
131 char *ip
; /* ptr into optstring, traverses every char */
132 char *op
; /* pointer into opt */
133 int match
; /* nonzero if opt is matching part of optstring */
135 cp
= ip
= (char *)optstring
;
137 if (*ip
!= '(' && *++ip
== '\0')
139 if (*ip
== ':' && *++ip
== '\0')
146 while (*ip
!= ')' && *ip
!= '\0' && *op
!= '\0')
147 match
= (*ip
++ == *op
++ && match
);
148 if (match
&& *ip
== ')' &&
149 (*op
== '\0' || *op
== '=')) {
151 /* may be an empty string - OK */
152 (*longoptarg
) = op
+ 1;
154 (*longoptarg
) = NULL
;
158 if (*ip
== ')' && *++ip
== '\0')
163 * Handle double-colon in optstring ("a::(longa)")
164 * The old getopt() accepts it and treats it as a
167 while ((cp
> optstring
) && ((*cp
) == ':')) {
170 } while (*cp
!= '\0');
175 * External function entry point.
178 getopt(int argc
, char *const *argv
, const char *optstring
)
186 * Has the end of the options been encountered? The following
187 * implements the SUS requirements:
189 * If, when getopt() is called:
190 * argv[optind] is a null pointer
191 * *argv[optind] is not the character '-'
192 * argv[optind] points to the string "-"
193 * getopt() returns -1 without changing optind. If
194 * argv[optind] points to the string "--"
195 * getopt() returns -1 after incrementing optind.
198 if (optind
>= argc
|| argv
[optind
][0] != '-' ||
199 argv
[optind
] == NULL
|| argv
[optind
][1] == '\0')
201 else if (strcmp(argv
[optind
], "--") == 0) {
208 * Getting this far indicates that an option has been encountered.
209 * Note that the syntax of optstring applies special meanings to
210 * the characters ':' and '(', so they are not permissible as
211 * option letters. A special meaning is also applied to the ')'
212 * character, but its meaning can be determined from context.
213 * Note that the specification only requires that the alnum
214 * characters be accepted.
216 * If the second character of the argument is a '-' this must be
217 * a long-option, otherwise it must be a short option. Scan for
218 * the option in optstring by the appropriate algorithm. Either
219 * scan will return a pointer to the short-option character in
220 * optstring if the option is found and NULL otherwise.
222 * For an unrecognized long-option, optopt will equal 0, but
223 * since long-options can't aggregate the failing option can
224 * be identified by argv[optind-1].
226 optopt
= c
= (unsigned char)argv
[optind
][_sp
];
228 longopt
= (_sp
== 1 && c
== '-');
230 ((cp
= parselong(optstring
, argv
[optind
]+2, &longoptarg
)) != NULL
) :
231 ((cp
= parseshort(optstring
, c
)) != NULL
))) {
232 ERR(_libc_gettext("%s: illegal option -- %s\n"),
233 c
, (longopt
? optind
: 0));
235 * Note: When the long option is unrecognized, optopt
236 * will be '-' here, which matches the specification.
238 if (argv
[optind
][++_sp
] == '\0' || longopt
) {
247 * A valid option has been identified. If it should have an
248 * option-argument, process that now. SUS defines the setting
249 * of optarg as follows:
251 * 1. If the option was the last character in the string pointed to
252 * by an element of argv, then optarg contains the next element
253 * of argv, and optind is incremented by 2. If the resulting
254 * value of optind is not less than argc, this indicates a
255 * missing option-argument, and getopt() returns an error
258 * 2. Otherwise, optarg points to the string following the option
259 * character in that element of argv, and optind is incremented
262 * The second clause allows -abcd (where b requires an option-argument)
263 * to be interpreted as "-a -b cd".
265 * Note that the option-argument can legally be an empty string,
267 * command --option= operand
268 * which explicitly sets the value of --option to nil
270 if (*(cp
+ 1) == ':') {
271 /* The option takes an argument */
272 if (!longopt
&& argv
[optind
][_sp
+1] != '\0') {
273 optarg
= &argv
[optind
++][_sp
+1];
274 } else if (longopt
&& longoptarg
) {
276 * The option argument was explicitly set to
277 * the empty string on the command line (--option=)
281 } else if (++optind
>= argc
) {
282 ERR(_libc_gettext("%s: option requires an argument" \
283 " -- %s\n"), c
, (longopt
? optind
- 1 : 0));
286 return (optstring
[0] == ':' ? ':' : '?');
288 optarg
= argv
[optind
++];
291 /* The option does NOT take an argument */
292 if (longopt
&& (longoptarg
!= NULL
)) {
293 /* User supplied an arg to an option that takes none */
295 "%s: option doesn't take an argument -- %s\n"),
296 0, (longopt
? optind
: 0));
297 optarg
= longoptarg
= NULL
;
301 if (longopt
|| argv
[optind
][++_sp
] == '\0') {