xref: /f-stack/tools/compat/getopt.c (revision 1eaf0ac3)
1144c6bcdSlogwang /*	$NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $	*/
2144c6bcdSlogwang 
3144c6bcdSlogwang /*
4144c6bcdSlogwang  * Copyright (c) 1987, 1993, 1994
5144c6bcdSlogwang  *	The Regents of the University of California.  All rights reserved.
6144c6bcdSlogwang  *
7144c6bcdSlogwang  * Redistribution and use in source and binary forms, with or without
8144c6bcdSlogwang  * modification, are permitted provided that the following conditions
9144c6bcdSlogwang  * are met:
10144c6bcdSlogwang  * 1. Redistributions of source code must retain the above copyright
11144c6bcdSlogwang  *    notice, this list of conditions and the following disclaimer.
12144c6bcdSlogwang  * 2. Redistributions in binary form must reproduce the above copyright
13144c6bcdSlogwang  *    notice, this list of conditions and the following disclaimer in the
14144c6bcdSlogwang  *    documentation and/or other materials provided with the distribution.
15144c6bcdSlogwang  * 3. Neither the name of the University nor the names of its contributors
16144c6bcdSlogwang  *    may be used to endorse or promote products derived from this software
17144c6bcdSlogwang  *    without specific prior written permission.
18144c6bcdSlogwang  *
19144c6bcdSlogwang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20144c6bcdSlogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21144c6bcdSlogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22144c6bcdSlogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23144c6bcdSlogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24144c6bcdSlogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25144c6bcdSlogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26144c6bcdSlogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27144c6bcdSlogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28144c6bcdSlogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29144c6bcdSlogwang  * SUCH DAMAGE.
30144c6bcdSlogwang  */
31144c6bcdSlogwang 
32144c6bcdSlogwang #if defined(LIBC_SCCS) && !defined(lint)
33144c6bcdSlogwang static char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
34144c6bcdSlogwang #endif /* LIBC_SCCS and not lint */
35144c6bcdSlogwang #include <sys/cdefs.h>
36144c6bcdSlogwang #ifndef FSTACK
37144c6bcdSlogwang __FBSDID("$FreeBSD$");
38144c6bcdSlogwang 
39144c6bcdSlogwang #include "namespace.h"
40144c6bcdSlogwang #endif
41144c6bcdSlogwang #include <stdio.h>
42144c6bcdSlogwang #include <stdlib.h>
43144c6bcdSlogwang #include <string.h>
44144c6bcdSlogwang #include <unistd.h>
45144c6bcdSlogwang #ifndef FSTACK
46144c6bcdSlogwang #include "un-namespace.h"
47144c6bcdSlogwang 
48144c6bcdSlogwang #include "libc_private.h"
49*1eaf0ac3Slogwang #else
50*1eaf0ac3Slogwang #include "compat.h"
51144c6bcdSlogwang #endif
52144c6bcdSlogwang 
53144c6bcdSlogwang int	opterr = 1,		/* if error message should be printed */
54144c6bcdSlogwang 	optind = 1,		/* index into parent argv vector */
55144c6bcdSlogwang 	optopt,			/* character checked for validity */
56144c6bcdSlogwang 	optreset;		/* reset getopt */
57144c6bcdSlogwang char	*optarg;		/* argument associated with option */
58144c6bcdSlogwang 
59144c6bcdSlogwang #define	BADCH	(int)'?'
60144c6bcdSlogwang #define	BADARG	(int)':'
61144c6bcdSlogwang #define	EMSG	""
62144c6bcdSlogwang 
63144c6bcdSlogwang /*
64144c6bcdSlogwang  * getopt --
65144c6bcdSlogwang  *	Parse argc/argv argument vector.
66144c6bcdSlogwang  */
67144c6bcdSlogwang int
getopt(int nargc,char * const nargv[],const char * ostr)68144c6bcdSlogwang getopt(int nargc, char * const nargv[], const char *ostr)
69144c6bcdSlogwang {
70144c6bcdSlogwang 	static char *place = EMSG;		/* option letter processing */
71144c6bcdSlogwang 	char *oli;				/* option letter list index */
72144c6bcdSlogwang 
73144c6bcdSlogwang 	if (optreset || *place == 0) {		/* update scanning pointer */
74144c6bcdSlogwang 		optreset = 0;
75144c6bcdSlogwang 		place = nargv[optind];
76144c6bcdSlogwang 		if (optind >= nargc || *place++ != '-') {
77144c6bcdSlogwang 			/* Argument is absent or is not an option */
78144c6bcdSlogwang 			place = EMSG;
79144c6bcdSlogwang 			return (-1);
80144c6bcdSlogwang 		}
81144c6bcdSlogwang 		optopt = *place++;
82144c6bcdSlogwang 		if (optopt == '-' && *place == 0) {
83144c6bcdSlogwang 			/* "--" => end of options */
84144c6bcdSlogwang 			++optind;
85144c6bcdSlogwang 			place = EMSG;
86144c6bcdSlogwang 			return (-1);
87144c6bcdSlogwang 		}
88144c6bcdSlogwang 		if (optopt == 0) {
89144c6bcdSlogwang 			/* Solitary '-', treat as a '-' option
90144c6bcdSlogwang 			   if the program (eg su) is looking for it. */
91144c6bcdSlogwang 			place = EMSG;
92144c6bcdSlogwang 			if (strchr(ostr, '-') == NULL)
93144c6bcdSlogwang 				return (-1);
94144c6bcdSlogwang 			optopt = '-';
95144c6bcdSlogwang 		}
96144c6bcdSlogwang 	} else
97144c6bcdSlogwang 		optopt = *place++;
98144c6bcdSlogwang 
99144c6bcdSlogwang 	/* See if option letter is one the caller wanted... */
100144c6bcdSlogwang 	if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
101144c6bcdSlogwang 		if (*place == 0)
102144c6bcdSlogwang 			++optind;
103144c6bcdSlogwang 		if (opterr && *ostr != ':')
104144c6bcdSlogwang 			(void)fprintf(stderr,
105144c6bcdSlogwang #ifndef FSTACK
106144c6bcdSlogwang 			    "%s: illegal option -- %c\n", _getprogname(),
107144c6bcdSlogwang #else
108*1eaf0ac3Slogwang 			    "%s: illegal option -- %c\n", getprogname(),
109144c6bcdSlogwang #endif
110144c6bcdSlogwang 			    optopt);
111144c6bcdSlogwang 		return (BADCH);
112144c6bcdSlogwang 	}
113144c6bcdSlogwang 
114144c6bcdSlogwang 	/* Does this option need an argument? */
115144c6bcdSlogwang 	if (oli[1] != ':') {
116144c6bcdSlogwang 		/* don't need argument */
117144c6bcdSlogwang 		optarg = NULL;
118144c6bcdSlogwang 		if (*place == 0)
119144c6bcdSlogwang 			++optind;
120144c6bcdSlogwang 	} else {
121144c6bcdSlogwang 		/* Option-argument is either the rest of this argument or the
122144c6bcdSlogwang 		   entire next argument. */
123144c6bcdSlogwang 		if (*place)
124144c6bcdSlogwang 			optarg = place;
125144c6bcdSlogwang 		else if (oli[2] == ':')
126144c6bcdSlogwang 			/*
127144c6bcdSlogwang 			 * GNU Extension, for optional arguments if the rest of
128144c6bcdSlogwang 			 * the argument is empty, we return NULL
129144c6bcdSlogwang 			 */
130144c6bcdSlogwang 			optarg = NULL;
131144c6bcdSlogwang 		else if (nargc > ++optind)
132144c6bcdSlogwang 			optarg = nargv[optind];
133144c6bcdSlogwang 		else {
134144c6bcdSlogwang 			/* option-argument absent */
135144c6bcdSlogwang 			place = EMSG;
136144c6bcdSlogwang 			if (*ostr == ':')
137144c6bcdSlogwang 				return (BADARG);
138144c6bcdSlogwang 			if (opterr)
139144c6bcdSlogwang 				(void)fprintf(stderr,
140144c6bcdSlogwang #ifndef FSTACK
141144c6bcdSlogwang 				    "%s: option requires an argument -- %c\n",
142144c6bcdSlogwang 				    _getprogname(), optopt);
143144c6bcdSlogwang #else
144*1eaf0ac3Slogwang 				    "%s: option requires an argument -- %c\n",
145*1eaf0ac3Slogwang 				    getprogname(), optopt);
146144c6bcdSlogwang #endif
147144c6bcdSlogwang 			return (BADCH);
148144c6bcdSlogwang 		}
149144c6bcdSlogwang 		place = EMSG;
150144c6bcdSlogwang 		++optind;
151144c6bcdSlogwang 	}
152144c6bcdSlogwang 	return (optopt);			/* return option letter */
153144c6bcdSlogwang }
154